Является ли & * NULL корректным в C?

Какая версия стандартов С (если таковая имеется) является следующей четко определенной?

void foo(void) {
    char *nullPtr = NULL;
    &*nullPtr;
}

Обратите внимание, что я не присваиваю результат чему-либо - вторая строка - это простой оператор.

Это должен быть вопрос с очевидным ответом, но (как это часто случается слишком часто по таким вопросам), я слышал, как многие люди говорят, что ответ "явно не определен" как "явно определенный".

Что относительно следующего примечания, как насчет следующего? Должен ли foo производить чтение c?

extern volatile char c;

void bar(void) {
    volatile char *nonnullptr = &c;
    &*nonnullptr;
}

(C++ версия того же вопроса: Is & * NULL четко определен в C++?)

Ответы

Ответ 1

Хотя попытки разыменовать нулевой указатель вызывают неопределенное поведение, поэтому *nullPtr является незаконным, &*nullPtr отлично определен. Согласно сноске 102 в проекте стандарта С11:

Таким образом, & * E эквивалентно E (даже если E - нулевой указатель),....

Это связано с тем, что для унарного оператора & (§6.5.3.2 ¶3):

Если операнд является результатом унарного * оператора, то ни этот оператор, ни оператор & не оцениваются, и результат как бы опускается,....

Стандарт C99 имеет тот же язык, но это не отображается в стандарте C90, и мое чтение этого стандарта заключается в том, что &*nullPtr действительно приведет к неопределенному поведению в реализациях до C99.

Из стандарта C90 (§6.3.2.3):

Результатом унарного & (адрес-оператора) является указатель на объект или функцию, назначенные его операндом....

а также:

Оператор унарного * обозначает косвенность.... Если для указателя было присвоено недопустимое значение, поведение унарного * оператора не определено.

Любопытно, что я не вижу никакого обсуждения этого изменения в Обосновании C99, хотя я просто не могу его найти.