Несоответствие упрощения адресации стандарта C

Раздел §6.5.3.2 «Операторы адреса и косвенного обращения» ¶3 говорит (только соответствующий раздел):

Унарный оператор & возвращает адрес его операнд. ... Оператор возвращает адрес своего операнда. ... Оператор возвращает адрес своего операнда. ... Если операнд является результатом унарного оператора * , ни этот оператор, ни оператор & не оцениваются, и результат такой, как если бы оба были опущены, за исключением того, что ограничения на операторы все еще применяется, и результат не является 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 и ЧИСЛО (10). Стандарт кажется очень ясным, что оба этих случая необходимо оптимизировать.

Однако это не так. Похоже, для оптимизации требуется следующее:

struct { int a; short b; } tmp, *s = tmp;
printf("%ti\n", (ptrdiff_t) (&s->b - s) );

Это кажется ужасно непоследовательным. Я не вижу причин, по которым приведенный выше код не должен печатать sizeof (int) плюс (маловероятно) заполнение (возможно 4).

Упрощение выражения & -> - это концептуально будет таким же (IMHO), что и и [] , простой адрес плюс смещение. Это даже смещение, которое будет определяться во время компиляции, а не во время выполнения с помощью оператора [] .

Есть ли какое-нибудь объяснение того, почему это кажется непоследовательным?

11
задан Kevin Reid 4 June 2013 в 14:32
поделиться