vectores que punteros puntero matrices lenguaje funciones ejemplo con c language-lawyer

que - Es((void*) 0) una constante de puntero nulo?



punteros y vectores en c (2)

¿La frase en negrita no contradice la afirmación del autor de que ((void*)0) no es una constante de puntero nulo?

No, no es así. (Confieso que soy un poco parcial, ya que el blog al que se hace referencia es mío).

La oración en negrita dice que su tipo y valor son idénticos a los de la expresión sin parentesis. Eso no es suficiente para implicar que es una constante de puntero nulo.

Considerar:

void *var = 0;

(void*)0 es una constante de puntero nulo. ((void*)0) tiene el mismo tipo y valor que (void*)0 . var también tiene el mismo tipo y valor que (void*)0 , pero var claramente no es una constante de puntero nulo.

Dicho esto, estoy 99% seguro de que la intención es que ((void*)0) es una constante de puntero nulo, y más generalmente que cualquier constante de puntero nulo entre paréntesis es una constante de puntero nulo. Los autores de la norma simplemente se olvidaron de decirlo. Y dado que la descripción de las expresiones entre paréntesis en 6.5.1p5 enumera específicamente otras características que son heredadas por las expresiones entre paréntesis:

Una expresión entre paréntesis es una expresión primaria. Su tipo y valor son idénticos a los de la expresión sin paréntesis. Es un lvalue, un designador de función o una expresión vacía si la expresión sin parche es, respectivamente, un lvalue, un designador de función o una expresión vacía.

la omisión es preocupante (pero solo levemente).

Pero supongamos, por el bien del argumento, que ((void*)0) no es una constante de puntero nulo. ¿Qué diferencia hace?

(void*)0 es una constante de puntero nulo, cuyo valor es un puntero nulo de tipo void* , por lo tanto, por la semántica de las expresiones entre paréntesis ((void*)0) también tiene un valor que es un puntero nulo de tipo void* . Ambos (void*)0 y ((void*)0) son constantes de dirección . (Bueno, creo que lo son). Entonces, ¿qué contextos requieren una constante de puntero nulo y no aceptan una constante de dirección ? Sólo hay unos pocos.

6.5.9 Operadores de igualdad

Una expresión del tipo de puntero de función se puede comparar para la igualdad con una constante de puntero nula. (Un puntero de objeto puede compararse con una expresión de tipo void* , pero un puntero de función puede no, a menos que sea una constante de puntero nulo). Así que esto:

void func(void); if (func == ((void*)0)) { /* ... */ }

Sería una violación de restricción.

6.5.16.1 Asignación simple

En una asignación, se puede asignar una constante de puntero nulo a un objeto de tipo puntero a función, y se convertirá implícitamente. Una expresión de tipo void* que no sea una constante de puntero nulo no se puede asignar a un puntero de función. Las mismas restricciones se aplican al paso e inicialización de argumentos. Así que esto:

void (*fp)(void) = ((void*)0);

Sería una violación de restricción si ((void*)0) no fuera una constante de puntero nulo. Gracias a commenter hvd por encontrar esto.

7.19 Definiciones comunes <stddef.h>

La macro NULL expande a "una constante de puntero nulo definida por la implementación". Si ((void*)0) no es una constante de puntero nula, entonces esto:

#define NULL ((void*)0)

sería inválido Esto sería una restricción impuesta a la implementación, no a los programadores. Tenga en cuenta que esto:

#define NULL (void*)0

es definitivamente inválido, ya que las definiciones de macro en encabezados estándar deben estar completamente protegidas por paréntesis cuando sea necesario (7.1.2p5). Sin los paréntesis, el sizeof NULL expresión válida de sizeof NULL sería un error de sintaxis, expandiéndose a sizeof (void*) seguido de una constante extraña 0 .

Estoy leyendo esta publicación de blog y en la sección Constantes de puntero nulo y expresiones entre paréntesis, el autor hace referencia a los § 6.3.2.3 y § 6.5.1 del estándar ISO C y dice:

No dice que una constante de puntero nulo entre paréntesis sea una constante de puntero nulo.

Lo que implica, estrictamente hablando, que (void*)0 es una constante de puntero nulo, pero ((void*)0) no lo es.

Entonces:

Estoy seguro de que la mayoría de las implementaciones C tratan una constante de puntero nulo entre paréntesis como una constante de puntero nulo, y definen NULL como 0 , ((void*)0) o de alguna otra manera.

Las dos secciones referenciadas dicen:

§ 6.3.2.3

Una expresión de constante entera con el valor 0, o una expresión de este tipo convertida en tipo void *, se denomina constante de puntero nula.

§ 6.5.1

Una expresión entre paréntesis es una expresión primaria. Su tipo y valor son idénticos a los de la expresión sin paréntesis. Es un lvalue, un designador de función o una expresión vacía si la expresión sin parche es, respectivamente, un lvalue, un designador de función o una expresión vacía.

¿La frase en negrita no contradice la afirmación del autor de que ((void*)0) no es una constante de puntero nulo?


Es una expresión entre paréntesis que contiene una constante de puntero nulo, por lo que es indiscutiblemente un valor de puntero nulo. Usarlo como un valor de r tiene exactamente el mismo efecto que usar la versión "compatible" como un valor de r.

Si hubiera algunas reglas sintácticas que solo pudieran aceptar una constante de puntero nulo, no calificaría. Pero no tengo conocimiento de ninguno (aunque soy menos experto en C).

Y si bien ninguna de las dos es una constante (en referencia a la producción gramatical formal), ambas pueden aparecer en una expresión constante en un inicializador, porque se permiten las constantes de puntero nulo y las constantes de dirección, y se incluye explícitamente un valor de puntero nulo constante en la categoría de la dirección constante .

Las comparaciones con el puntero también mencionan específicamente las constantes del puntero nulo ... pero aquí también se aceptan los valores del puntero, y todos los valores del puntero nulo se tratan por igual. Lo mismo para los operadores ternarios y de asignación.

Tenga en cuenta que estas reglas son bastante diferentes en C ++, donde las dos expresiones anteriores son valores de puntero nulos constantes de tipo void* , pero no constantes universales de puntero nulo. Las constantes de puntero nulas en C ++ son expresiones constantes integrales que se evalúan en cero. Y void* no se convierte implícitamente a otros tipos de punteros.