Раздел §6.5.3.2 «Операторы адреса и косвенности» says3 гласит (только соответствующий раздел):
Унарный оператор & возвращает адрес своего операнда.... Если операнд является результатом унарного оператора *
, ни этот оператор, ни оператор &
не оцениваются, и результат такой, как если бы оба опущены, за исключением того, что ограничения на операторы все еще применяются и результатэто не lvalue.Точно так же, если операнд является результатом оператора []
, ни оператор &
, ни унарный *
, подразумеваемый []
, не оцениваются, и результат такой, как если бы оператор &
был удалени оператор []
был изменен на оператор +
....
Это означает, что это:
#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)
plus (маловероятно) (возможно, 4).
Упрощение выражения &->
будет концептуально таким же (ИМХО), что и&[]
, простой адрес плюс смещение.Это даже смещение, которое будет определяться во время компиляции, а не потенциально во время выполнения с оператором []
.
Есть ли что-нибудь в обосновании того, почему это так на вид несовместимо?