¿Qué significa EXACTAMENTE “desreferenciando un puntero NULL”?

Soy un novato completo para C, y durante mi trabajo en la universidad he encontrado comentarios en el código que a menudo se refieren a la eliminación de referencias a un puntero NULL. Tengo antecedentes en C #, he estado entendiendo que esto podría ser similar a una “NullReferenceException” que obtienes en .Net, pero ahora estoy teniendo serias dudas.

¿Puede alguien por favor explicarme en términos de laymans exactamente qué es esto y por qué es malo?

Un puntero NULL apunta a la memoria que no existe. Puede ser la dirección 0x00000000 o cualquier otro valor definido por la implementación (siempre que nunca pueda ser una dirección real). Desreferencia significa intentar acceder a lo que apunta el puntero. El operador * es el operador de desreferenciación:

 int a, b, c; // some integers int *pi; // a pointer to an integer a = 5; pi = &a; // pi points to a b = *pi; // b is now 5 pi = NULL; c = *pi; // this is a NULL pointer dereference 

Esto es exactamente lo mismo que una NullReferenceException en C #, excepto que los punteros en C pueden apuntar a cualquier objeto de datos, incluso elementos dentro de una matriz.

La desreferenciación solo significa leer el valor de la memoria en una dirección determinada. Por lo tanto, cuando tiene un puntero a algo, para desreferenciar el puntero significa leer o escribir los datos a los que apunta el puntero.

En C, el operador unario * es el operador de desreferenciación. Si x es un puntero, entonces *x es a lo que x apunta. El operador unario es el operador de dirección . Si x es cualquier cosa, entonces &x es la dirección en la que x se almacena en la memoria. Los operadores * y & son inversos entre sí: si x es cualquier dato, y y es cualquier apuntador, entonces estas ecuaciones son siempre verdaderas:

 *(&x) == x &(*y) == y 

Un puntero nulo es un puntero que no apunta a ningún dato válido (pero no es el único puntero). El estándar C dice que es un comportamiento indefinido desreferenciar un puntero nulo. Esto significa que podría pasar absolutamente cualquier cosa: el progtwig podría fallar, podría seguir funcionando silenciosamente o podría borrar tu disco duro (aunque eso es bastante improbable).

En la mayoría de las implementaciones, obtendrá un “error de segmentación” o “infracción de acceso” si intenta hacerlo, lo que casi siempre dará lugar a que su progtwig sea terminado por el sistema operativo. Esta es una forma de desreferenciar un puntero nulo:

 int *x = NULL; // x is a null pointer int y = *x; // CRASH: dereference x, trying to read it *x = 0; // CRASH: dereference x, trying to write it 

Y sí, eliminar referencias de un puntero nulo es más o menos exactamente como una NullReferenceException en C # (o una NullPointerException en Java), excepto que el estándar de idioma es un poco más útil aquí. En C #, la eliminación de referencia de una referencia nula tiene un comportamiento bien definido: siempre arroja una NullReferenceException . No hay forma de que su progtwig continúe funcionando silenciosamente o borre su disco duro como en C (a menos que haya un error en el tiempo de ejecución del lenguaje, pero de nuevo eso también es increíblemente improbable).

Significa

 myclass *p = NULL; *p = ...; // illegal: dereferencing NULL pointer ... = *p; // illegal: dereferencing NULL pointer p->meth(); // illegal: equivalent to (*p).meth(), which is dereferencing NULL pointer myclass *p = /* some legal, non-NULL pointer */; *p = ...; // Ok ... = *p; // Ok p->meth(); // Ok, if myclass::meth() exists 

básicamente, casi cualquier cosa que implique (*p) o que implique implícitamente (*p) , por ejemplo, p->... que es una abreviación de (*p). ... (*p). ... ; a excepción de la statement del puntero.

De wiki

Un puntero nulo tiene un valor reservado, a menudo pero no necesariamente el valor cero, lo que indica que no se refiere a ningún objeto
..

Dado que un puntero de valor nulo no se refiere a un objeto significativo, un bash de desreferencia de un puntero nulo generalmente causa un error de tiempo de ejecución.

 int val =1; int *p = NULL; *p = val; // Whooosh!!!! 

Citando de wikipedia :

Un puntero hace referencia a una ubicación en la memoria, y obtener el valor en la ubicación a la que hace referencia el puntero se conoce como desreferenciación del puntero.

La desreferenciación se realiza aplicando el unary * en el puntero.

 int x = 5; int * p; // pointer declaration p = &x; // pointer assignment *p = 7; // pointer dereferencing, example 1 int y = *p; // pointer dereferencing, example 2 

“Desreferenciando un puntero NULL” significa ejecutar *p cuando el p es NULL