array - pointers significado
¿Qué significa EXACTAMENTE "desreferenciando un puntero NULL"? (5)
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?
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
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 intento de desreferencia de un puntero nulo generalmente causa un error de tiempo de ejecución.
int val =1;
int *p = NULL;
*p = val; // Whooosh!!!!
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 declaración del puntero.
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 programa 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 programa 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 programa 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).
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.