【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.22309

配列に対するアドレス演算子
投稿者---Hermit(2005/07/30 10:38:22)


char foo[5];

の、foo に対するアドレス演算子、(&foo)
2種類あったはずだけど、どう違ってたのか思い出せなかったので、
ちょっとチェックしてみましたが、
単純に、
gcc,lsic86 -> char (*foo)[5] (sizeof(&foo)が 4 )
VC++,BC++ -> foo[1][5] (かな?sizeof(&foo)が 5 なので)
だけでしたね。
2種類あることだけ記憶に残っていたので、
いらぬことを書いてしまいました。

ということで、上記の違いにより、
sizeof したときの値が変わります。

あと、今はエラーですが、VC++,BC++ 系列のどちらかの古いものでは
(MSC,TC含む。ただし、ANSI C ではあるけどどのバージョンか不明)
&&foo を許していたものもあったはずですが、
現在のものはどちらもエラーになることを確認しました。
(BC++5.51 VC++2003Toolkit)

ということで、ANSI 1999 ではどちらかに決まったんでしょうか?
20世紀末位に上った話題だったけど(^^;


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:配列に対するアドレス演算子 22313 かずま 2005/07/30 18:49:50
<子記事> Re:配列に対するアドレス演算子 22350 YuO 2005/08/01 11:24:01


No.22313

Re:配列に対するアドレス演算子
投稿者---かずま(2005/07/30 18:49:50)


> char foo[5];
>
> の、foo に対するアドレス演算子、(&foo)
> 2種類あったはずだけど、どう違ってたのか思い出せなかったので、
> ちょっとチェックしてみましたが、
> 単純に、
> gcc,lsic86 -> char (*foo)[5] (sizeof(&foo)が 4 )
> VC++,BC++ -> foo[1][5] (かな?sizeof(&foo)が 5 なので)
> だけでしたね。

LSI C-86 の試食版なら、メモリモデルとしてスモールモデルしか
コンパイルできませんから、ポインタのサイズは 2 のはずです。

さて、&foo ですが、アドレス演算子はポインタを返しますから、そのサイズ
が 5 になることはないはずです。
したがって、VC++ と BC++ は、sizeof(&foo) に関してはバグといえます。た
だ、コンパイラ作成者の気持ちを考えると、なぜそうなったかが想像できます。

式の中では、配列はポインタに変換されるという規則があります。
ただし、配列が、sizeof のオペランドである場合と、単項&演算子のオペラン
ドの場合には配列のままという例外規則があります。

foo は配列で、&のオペランドだから、配列のままだ。foo をポインタに変換し
てはいけないんだ。だから、&演算子によるポインタへの変換もやめておこう。
&foo は foo と同じ配列だ。sizeof のオペランドが配列だから、ポインタには
変換せずにその配列のサイズを結果としよう。

たぶん、VC++ も BC++ もこんな風にコンパイラが作られているのでしょう。


> あと、今はエラーですが、VC++,BC++ 系列のどちらかの古いものでは
> (MSC,TC含む。ただし、ANSI C ではあるけどどのバージョンか不明)
> &&foo を許していたものもあったはずですが、
> 現在のものはどちらもエラーになることを確認しました。
> (BC++5.51 VC++2003Toolkit)

いいえ、BC++ 5.5.1 には、まだそのバグがあります。次のプログラムが
エラーになりません。
    char foo[5];
    printf("& &foo = %p\n", & &foo);



この投稿にコメントする

削除パスワード

No.22315

Re:配列に対するアドレス演算子
投稿者---Hermit(2005/07/30 21:35:32)


>LSI C-86 の試食版なら、メモリモデルとしてスモールモデルしか
>コンパイルできませんから、ポインタのサイズは 2 のはずです。
突っ込まれるかなとは思いましたが(^^;

>さて、&foo ですが、アドレス演算子はポインタを返しますから、そのサイズ
>が 5 になることはないはずです。
<中略>
>たぶん、VC++ も BC++ もこんな風にコンパイラが作られているのでしょう。
昔、Nifty の fc でも検討されたようですが、
普通に考えるとポインタサイズにしか読めないけど、
配列サイズで返してはいけないという根拠がどうしても見出せなかった様です。
今は、VC++,BC++のバグであるという風に考えられているんでしょうか。
TC++Ver1.0 だったとおもいますが、
C では、配列サイズ
C++ では、ポインタサイズ
という時もあったので、結構迷いなから作ってるんだろうな。

>いいえ、BC++ 5.5.1 には、まだそのバグがあります。次のプログラムが
>エラーになりません。

char foo[5];
printf("& &foo = %p\n", & &foo);


仕様かと思ったんですが、バグでしたか、知らなかった (^^;







この投稿にコメントする

削除パスワード

No.22350

Re:配列に対するアドレス演算子
投稿者---YuO(2005/08/01 11:24:01)


>単純に、
>gcc,lsic86 -> char (*foo)[5] (sizeof(&foo)が 4 )
>VC++,BC++ -> foo[1][5] (かな?sizeof(&foo)が 5 なので)
>だけでしたね。

違いますね。
VC++とBCCは,
sizeof(&foo)
の値に関してバグがある,というだけです。
BCCはさらに,
typeid(&foo).name()
char[5]を返すバグもあります。

ただし,例えば
void func(char (*)[5]);
と宣言された関数に,
&fooを渡した場合,警告も出ずに渡すことができますし,
&foo + 1の値も正しい値になっています。


>ということで、ANSI 1999 ではどちらかに決まったんでしょうか?
>20世紀末位に上った話題だったけど(^^;

1990年発行のISOから変化がありません。
配列に単項&演算子をつければ配列へのポインタを生成しますし,
単項&演算子はポインタという値(=左辺値ではない)を生成するので,
単項&演算子を適用したものにさらに単項&演算子を適用することは文法エラーです。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧