|
> 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);
|