2010-10-24 46 views
33

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.¿Qué significa EXACTAMENTE "desreferenciando un puntero NULL"?

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

+0

Tenga en cuenta que esto da como resultado un comportamiento indefinido. No obtiene excepciones ni nada, en C o C++. – GManNickG

+0

Es posible que desee dejar algún código de ejemplo. Parece que las personas (incluyéndome a mí) no entienden lo que intentas preguntar. –

+0

Sin necesidad de código (no hay ninguno) - Este es un problema conceptual que estoy teniendo, tratando de entender la terminología de "desreferenciación" y por qué debería preocuparme por ello. – Ash

Respuesta

47

A NULL puntero 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 desreferencia:

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 

Este es exactamente el mismo que un NullReferenceException en C#, excepto que los punteros en C puede apuntar a cualquier objeto de datos, incluso elementos dentro de una matriz.

+8

@Ash: un puntero contiene una dirección de memoria que * hace referencia * a algo. Para acceder a ese algo * referenciado * por esa dirección de memoria, tiene que * desmarcar * la dirección de memoria. –

+0

@Ash, lo que In silico dijo, pero cuando lo des referencia, obtiene el valor que está almacenado en la dirección de la memoria. Darle una oportunidad. Hacer int p; printf ("% p \ n", &p); debe imprimir una dirección. Cuando no crea un puntero (* var), para obtener la dirección que usa & var – Matt

+0

@Greg ¿Qué tal cuando 'char * foo = NULL' y luego usar & foo? – Bionix1441

-1

De wiki

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

Desde un puntero nulo de valor hace 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!!!! 
+0

Gracias por su respuesta, estoy de acuerdo con lo que era un puntero NULL, simplemente no estaba seguro de cómo encaja la "desreferencia" en el esquema de cosas . – Ash

2

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 implica (*p) o implícitamente implica (*p), por ejemplo, p->... que es una abreviatura de (*p). ...; a excepción de la declaración del puntero.

+0

Marcó su pregunta como C no C++ – GWW

+2

@GWW: y tiene exactamente la misma semántica en C y en C++, excepto que tal vez C no tiene clase costum. –

+0

No es 'p-> meth()' simplemente una abreviación para '(* p) .meth()', con el este último está disponible tanto en C como en C++? – Arun

0

Citando de wikipedia:

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

La desreferencia se realiza aplicando el operador 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 

"eliminación de referencias a un puntero NULL" significa la realización de *p cuando el p es NULL

20

Desreferenciar sólo significa leer el valor de la memoria en una dirección determinada. Por lo tanto, cuando tiene un puntero a algo, a desreferencia el puntero significa leer o escribir los datos a los que apunta el puntero.

En C, el operador * único es el operador de desreferenciación.Si x es un puntero, entonces *x es a lo que apunta x. El operador único & 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 * y & operadores son inversas entre sí: si x es cualquier dato, y y es cualquier indicador, a continuación, estas ecuaciones son siempre verdaderas:

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

un puntero nulo es un puntero que no apunta a ninguna válida datos (pero no es el único puntero). El estándar C dice que es comportamiento indefinido para 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. He aquí una forma en que un puntero nulo ha podido obtener:

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í, eliminación de referencias a un puntero nulo es casi exactamente como un NullReferenceException en C# (o una NullPointerException en Java), excepto que el estándar del lenguaje se ve un poco más útil aquí. En C#, la eliminación de referencia de una referencia nula tiene un comportamiento bien definido: siempre arroja un 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).

Cuestiones relacionadas