セクション §6.5.3.2「アドレスと間接演算子」¶3 は述べています (関連するセクションのみ):
単項 & 演算子は、そのオペランドのアドレスを返します。... オペランドが単項演算子の結果である場合、
*
その演算子も演算子も&
評価されず、演算子に対する制約が適用され、結果が左辺値ではないことを除いて、結果は両方が省略されたかのようになります。同様に、オペランドが演算子の結果である場合、演算[]
子もによって暗示される&
単項も評価されず、結果は、演算子が削除され、演算子が演算子に変更されたかのようになります。...*
[]
&
[]
+
これは、次のことを意味します。
#define NUM 10
int tmp[NUM];
int *i = tmp;
printf("%ti\n", (ptrdiff_t) (&*i - i) );
printf("%ti\n", (ptrdiff_t) (&i[NUM] - i) );
完全に合法で、0 とNUM
(10) を出力する必要があります。標準は、これらのケースの両方を最適化する必要があることを非常に明確に示しています。
ただし、以下を最適化する必要はないようです。
struct { int a; short b; } tmp, *s = tmp;
printf("%ti\n", (ptrdiff_t) (&s->b - s) );
これはひどく矛盾しているようです。sizeof(int)
上記のコードがプラスの (ありそうにない) パディング (おそらく 4)を出力してはならない理由はわかりません。
式を単純化することは、単純なアドレスとオフセットで&->
ある と概念的に (IMHO) 同じになります。これは、オペレーター&[]
を使用して実行する可能性があるのではなく、コンパイル時に決定できるオフセットですらあります。[]
これが一見矛盾しているように見える理由について、何か根拠はありますか?