¿Cuál es la diferencia entre NULL, '\0' y 0?

Resuelto gnavi asked hace 15 años • 11 respuestas

En C, parece haber diferencias entre varios valores de cero NULL-- NULy 0.

Sé que el carácter ASCII '0'se evalúa como 48o 0x30.

El NULLpuntero generalmente se define como:

#define NULL 0

O

#define NULL (void *)0

Además, está el NULpersonaje '\0'que parece evaluar 0también.

¿Hay ocasiones en las que estos tres valores no pueden ser iguales?

¿Esto también se aplica a los sistemas de 64 bits?

gnavi avatar Aug 19 '09 05:08 gnavi
Aceptado

Nota: Esta respuesta se aplica al lenguaje C, no a C++.


Punteros nulos

El literal constante entero 0tiene diferentes significados según el contexto en el que se utiliza. En todos los casos, sigue siendo una constante entera con el valor 0, simplemente se describe de diferentes maneras.

Si se compara un puntero con el literal constante 0, entonces se trata de una verificación para ver si el puntero es un puntero nulo. Esto 0se denomina entonces constante de puntero nulo. El estándar C define que 0la conversión al tipo void *es tanto un puntero nulo como una constante de puntero nulo.

Además, para facilitar la lectura, la macro NULLse proporciona en el archivo de encabezado stddef.h. Dependiendo de su compilador, podría ser posible #undef NULLredefinirlo como algo extraño.

Por lo tanto, aquí hay algunas formas válidas de comprobar si hay un puntero nulo:

if (pointer == NULL)

NULLse define para comparar igual a un puntero nulo. La implementación define cuál es la definición real NULL, siempre que sea una constante de puntero nulo válida.

if (pointer == 0)

0es otra representación de la constante de puntero nulo.

if (!pointer)

Esta ifdeclaración verifica implícitamente "no es 0", por lo que lo invertimos para que signifique "es 0".

Las siguientes son formas NO VÁLIDAS de comprobar si hay un puntero nulo:

int mynull = 0;
<some code>
if (pointer == mynull)

Para el compilador, esto no es una verificación de un puntero nulo, sino una verificación de igualdad de dos variables. Esto podría funcionar si mynull nunca cambia en el código y la constante de optimización del compilador agrega el 0 a la declaración if, pero esto no está garantizado y el compilador debe producir al menos un mensaje de diagnóstico (advertencia o error) de acuerdo con el estándar C.

Tenga en cuenta que el valor de un puntero nulo en el lenguaje C no importa en la arquitectura subyacente. Si la arquitectura subyacente tiene un valor de puntero nulo definido como dirección 0xDEADBEEF, entonces le corresponde al compilador solucionar este problema.

Como tal, incluso en esta curiosa arquitectura, las siguientes formas siguen siendo válidas para comprobar si hay un puntero nulo:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

Las siguientes son formas NO VÁLIDAS de comprobar si hay un puntero nulo:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

ya que un compilador los considera comparaciones normales.

Caracteres nulos

'\0'se define como un carácter nulo, es decir, un carácter con todos los bits establecidos en cero. '\0'es (como todos los caracteres literales) una constante entera, en este caso con el valor cero. So '\0'es completamente equivalente a una 0constante entera sin adornos; la única diferencia está en la intención que transmite a un lector humano ("Estoy usando esto como un carácter nulo").

'\0'No tiene nada que ver con punteros. Sin embargo, es posible que vea algo similar a este código:

if (!*char_pointer)

comprueba si el puntero char apunta a un carácter nulo.

if (*char_pointer)

comprueba si el puntero char apunta a un carácter no nulo.

No los confunda con punteros nulos. Sólo porque la representación de bits es la misma, y ​​esto permite algunos casos de cruce convenientes, en realidad no son lo mismo.

Referencias

Consulte la pregunta 5.3 de las preguntas frecuentes de comp.lang.c para obtener más información. Consulte este pdf para conocer el estándar C. Consulte las secciones 6.3.2.3 Consejos, párrafo 3.

Andrew Keeton avatar Aug 18 '2009 22:08 Andrew Keeton

Parece que varias personas no entienden cuáles son las diferencias entre NULL, '\0' y 0. Entonces, para explicar, y en un intento de evitar repetir lo dicho anteriormente:

Una expresión constante de tipo intcon el valor 0, o una expresión de este tipo, convertida a tipo void *es una constante de puntero nulo , que si se convierte en un puntero se convierte en un puntero nulo . El estándar garantiza la comparación desigual con cualquier puntero a cualquier objeto o función .

NULLes una macro, definida como una constante de puntero nulo .

\0es una construcción utilizada para representar el carácter nulo , que se utiliza para terminar una cadena.

Un carácter nulo es un byte que tiene todos sus bits puestos a 0.

amaterasu avatar Aug 18 '2009 22:08 amaterasu

Los tres definen el significado de cero en diferentes contextos.

  • Contexto del puntero: se utiliza NULL y significa que el valor del puntero es 0, independientemente de si es de 32 bits o de 64 bits (en un caso, 4 bytes y en el otro, 8 bytes de ceros).
  • contexto de cadena: el carácter que representa el dígito cero tiene un valor hexadecimal de 0x30, mientras que el carácter NUL tiene un valor hexadecimal de 0x00 (utilizado para terminar cadenas).

Estos tres siempre son diferentes cuando miras el recuerdo:

NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20

Espero que esto lo aclare.

Nasko avatar Aug 18 '2009 22:08 Nasko