Si un puntero a puntero es NULL, ¿es necesario que el puntero también sea NULL?
pointers (4)
Considera que tengo una estructura
typedef struct point_t
{
int x;
int y;
}POINT;
Creo un puntero a puntero para POINT y lo inicializo a
NULL
.
POINT **ppPoint = NULL;
¿Debería
*ppPoint
también devolver
NULL
?
El hecho de que haya 2 capas de punteros aquí es realmente irrelevante.
El hecho de que su puntero externo en
NULL
significa que es
ilegal
desreferenciarlo.
Por lo tanto, no tiene sentido preguntar qué valor obtendría al desreferenciarlo.
Considera esto:
int *p = NULL; // modern practice would be to use nullptr anyway
if (0 == *p) // this is Undefined Behaviour!
{
// do something, maybe?
}
Simplemente está agregando otra capa a esto, donde en lugar de
int
, tiene
point_t*
, pero realmente no hace ninguna diferencia.
¡Lo que ocurre con el comportamiento indefinido es que puede pasar cualquier cosa ! Su programa podría fallar, o podría parecer que funciona, o podría darle valores de basura a veces, o podría ...
No puede desreferenciar un puntero que tiene un valor de
NULL
.
Por lo tanto, no podrá acceder a
*ppPoint
.
Puede verificar la dirección de una variable con el formateador
%p
en un
printf()
para verificar.
printf("Address of ppPoint: %p", *ppPoint);
printf("Address of *ppPoint: %p", *ppPoint);
Primero, están los conceptos erróneos habituales sobre el nulo misterioso. En este caso hay 3 términos relacionados:
- puntero nulo
- puntero nulo constante
-
La macro
NULL
Una constante de puntero nulo es el entero
0
o ese entero convertido a un puntero,
(void*)0
.
Se garantiza que la macro
NULL
es una constante de puntero nulo portátil.
Cada vez que asigna una constante de puntero nulo, como
NULL
, a cualquier puntero, ese puntero se convierte en un
puntero nulo
.
Esto permite que los compiladores representen internamente un puntero nulo como algo más que
0
, porque la dirección
0x00...00
es a menudo una dirección física válida en muchos sistemas.
Específicamente, C17 6.3.2.3/3 define esto:
Una expresión constante entera con el valor
0
, o tal expresión emitida para escribirvoid *
, se llama constante de puntero nulo . Si una constante de puntero nulo se convierte en un tipo de puntero , se garantiza que el puntero resultante, llamado puntero nulo , se comparará desigual a un puntero con cualquier objeto o función.
Al acceder a un puntero nulo al desreferenciarlo, no obtendrá ningún resultado predecible. Este es un comportamiento indefinido según C17 6.5.3.2/4:
Si se ha asignado un valor no válido al puntero, el comportamiento del operador unario * no está definido.
Lo que significa que cualquier cosa puede suceder. Si tienes suerte, solo tienes un bloqueo del sistema.
Sin embargo, puede comparar un puntero nulo con otro puntero nulo, o con una constante de puntero nulo, y se garantiza que son iguales (C17 6.5.9).
En cuanto a que el puntero a puntero es un caso especial, no lo es. El tipo señalado es irrelevante para cualquiera de las reglas mencionadas anteriormente. En general, no hay nada especial con puntero a puntero en C: nunca es un caso especial, pero siempre debe considerarse como puntero a tipo.
Un puntero nulo no apunta a nada . Eso se aplica tanto a los punteros comunes como a los punteros funcionales y a los miembros. También se aplica a punteros a punteros.
Por lo tanto, no tiene sentido hablar sobre el valor de "a lo que apunta".