c language-lawyer

¿Está &*NULL bien definido en C?



language-lawyer (1)

¿En qué versión (s) de las normas C (si las hay) están bien definidas las siguientes?

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

Tenga en cuenta que no estoy asignando el resultado a nada: la segunda línea es una declaración simple.

Esta debería ser una pregunta con una respuesta obvia, pero (como parece suceder demasiado a menudo en esas preguntas) he escuchado que muchas personas dicen que la respuesta es "obviamente indefinida" como "obviamente definida".

En una nota más bien relacionada, ¿qué pasa con lo siguiente? ¿ foo debería producir una lectura de c?

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

(Versión de C ++ de la misma pregunta: ¿Está & * NULL bien definido en C ++? )


Si bien los intentos de anular la referencia a un puntero nulo causan un comportamiento indefinido, por lo que *nullPtr es ilegal, &*nullPtr está perfectamente bien definido. Según la nota de pie de página 102 en el Proyecto de Norma C11 :

Por lo tanto, & * E es equivalente a E (incluso si E es un puntero nulo), ...

Esto es un resultado del hecho de que, para el operador unario & ( §6.5.3.2 ¶3 ):

Si el operando es el resultado de un operador unario * , ni ese operador ni el operador & se evalúan y el resultado es como si ambos se omitieran, ...

El estándar C99 tiene el mismo lenguaje, pero esto no aparece en el estándar C90, y mi lectura de ese estándar es que &*nullPtr podría causar un comportamiento indefinido en las implementaciones anteriores a C99.

De la norma C90 (§6.3.2.3):

El resultado del operador unario & (dirección-de) es un puntero al objeto o función designado por su operando ...

y:

El operador unario * denota la dirección indirecta ... Si se ha asignado un valor no válido al puntero, el comportamiento del operador unario * no está definido.

Curiosamente, no veo ninguna discusión de este cambio en la Razón C99 , aunque es posible que simplemente no lo encuentre.