En C, parece haber diferencias entre varios valores de cero NULL
, NUL
y 0
.
Sé que el carácter ASCII se '0'
evalúa como 48
o 0x30
.
El NULL
puntero generalmente se define como:
#define NULL 0
O
#define NULL (void *)0
Además, está el NUL
personaje '\0'
que parece evaluar 0
también.
¿Hay momentos en que estos tres valores no pueden ser iguales?
¿Es esto también cierto en los sistemas de 64 bits?
NUL
no existe en el lenguaje estándar C o en la biblioteca (o en C ++, que yo sepa). El carácter nulo a veces se llama NUL, pero a C o C ++ generalmente se le conoce como'\0'
.Respuestas:
Nota: Esta respuesta se aplica al lenguaje C, no a C ++.
Punteros nulos
El entero constante literal
0
tiene diferentes significados según el contexto en el que se utiliza. En todos los casos, sigue siendo una constante entera con el valor0
, solo se describe de diferentes maneras.Si se compara un puntero con el literal constante
0
, entonces esta es una verificación para ver si el puntero es un puntero nulo. Esto0
se conoce como una constante de puntero nulo. El estándar C define que la0
conversión al tipovoid *
es tanto un puntero nulo como una constante de puntero nulo.Además, para ayudar a la legibilidad, la macro
NULL
se proporciona en el archivo de encabezadostddef.h
. Dependiendo de su compilador, podría ser posible#undef NULL
y redefinirlo en algo loco.Por lo tanto, aquí hay algunas formas válidas de verificar un puntero nulo:
NULL
se define para comparar igual a un puntero nulo. Es la implementación definida cuál es la definición real deNULL
, siempre que sea una constante de puntero nulo válida.0
es otra representación de la constante de puntero nulo.Esta
if
afirmación verifica implícitamente "no es 0", por lo que revertimos que significa "es 0".Las siguientes son formas NO VÁLIDAS de verificar un puntero nulo:
Para el compilador, esto no es una comprobación de un puntero nulo, sino una comprobación de igualdad en dos variables. Esto podría funcionar si mynull nunca cambia en el código y las optimizaciones del compilador constantemente doblan el 0 en la instrucción if, pero esto no está garantizado y el compilador tiene que producir al menos un mensaje de diagnóstico (advertencia o error) de acuerdo con el Estándar C.
Tenga en cuenta que lo que es 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 depende del compilador resolver este desorden.
Como tal, incluso en esta arquitectura divertida, las siguientes formas siguen siendo formas válidas de verificar un puntero nulo:
Las siguientes son formas NO VÁLIDAS de verificar un puntero nulo:
ya que estos son vistos por un compilador como comparaciones normales.
Personajes nulos
'\0'
se define como un carácter nulo, es decir, un carácter con todos los bits puestos a cero. Esto no tiene nada que ver con los punteros. Sin embargo, puede ver algo similar a este código:comprueba si el puntero de cadena apunta a un carácter nulo
comprueba si el puntero de cadena apunta a un carácter no nulo
No los confundas con punteros nulos. Solo porque la representación de bits es la misma, y esto permite algunos casos cruzados convenientes, en realidad no son lo mismo.
Además,
'\0'
es (como todos los literales de caracteres) una constante entera, en este caso con el valor cero. Por'\0'
lo tanto, es completamente equivalente a una0
constante 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").Referencias
Consulte la pregunta 5.3 de las preguntas frecuentes de comp.lang.c para obtener más información. Vea este pdf para el estándar C. Consulte las secciones 6.3.2.3 Punteros, párrafo 3.
fuente
ptr
con todos los bits cero . Esto no es unmemcmp
, pero es una comparación usando un operador incorporado. Un lado es una constante de puntero nulo'\0'
, y el otro lado es un puntero. Igual que con las otras dos versiones conNULL
y0
. Esos tres hacen lo mismo.0xDEADBEEF
sigue siendo un puntero nulo, no importa lo que les gusta su aspecto cadena de bits, y todavía se comparará igual aNULL
,0
,\0
y todas las demás formas constantes de puntero nulo.ptr == '\0'
.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 cosas que dije antes:
Una expresión constante de tipo
int
con el valor 0, o una expresión de este tipo, convertir a tipovoid *
es una constante de puntero nulo , que si se convierte en un puntero se convierte en un puntero nulo . Está garantizado por el estándar comparar desigual a cualquier puntero a cualquier objeto o función .NULL
es una macro, definida como una constante de puntero nulo .\0
es una construcción utilizada para representar el carácter nulo , utilizado para terminar una cadena.Un carácter nulo es un byte que tiene todos sus bits establecidos en 0.
fuente
Los tres definen el significado de cero en diferentes contextos.
Estos tres siempre son diferentes cuando miras la memoria:
Espero que esto lo aclare.
fuente
sizeof('\0')
y sorpréndete.Si NULL y 0 son equivalentes como constantes de puntero nulo, ¿qué debo usar? en la lista de preguntas frecuentes de C también se aborda este problema:
fuente
"carácter nulo (NUL)" es más fácil de descartar.
'\0'
Es un carácter literal. En C, se implementa comoint
, por lo tanto, es lo mismo que 0, que es deINT_TYPE_SIZE
. En C ++, el literal de caracteres se implementa comochar
, que es 1 byte. Esto normalmente es diferente deNULL
o0
.A continuación,
NULL
hay un valor de puntero que especifica que una variable no apunta a ningún espacio de direcciones. Deje de lado el hecho de que generalmente se implementa como ceros, debe poder expresar el espacio de direcciones completo de la arquitectura. Por lo tanto, en una arquitectura de 32 bits, NULL (probable) es de 4 bytes y en la arquitectura de 64 bits de 8 bytes. Esto depende de la implementación de C.Finalmente, el literal
0
es de tipoint
, que es de tamañoINT_TYPE_SIZE
. El valor predeterminado deINT_TYPE_SIZE
podría ser diferente según la arquitectura.Apple escribió:
Wikipedia de 64 bits :
Editar : se agregó más en el carácter literal.
El código anterior devuelve 4 en gcc y 1 en g ++.
fuente
'\0'
es un valor de 1 byte. Es un carácter literal, que es una expresión constante entera, por lo que si se puede decir que tiene un tamaño, entonces es el tamaño de un (que debe ser de al menos 2 bytes). Si no me crees, evalúa y comprueba por ti mismo. , y todos son completamente equivalentes.int
sizeof('\0')
'\0'
0
0x0
sizeof('\0')
un compilador de C ++.Un NUL de un L, termina una cadena.
Un NULL de dos L no apunta a nada.
Y apostaré un toro dorado
Que no hay tres-L NULLL.
¿Cómo lidias con NUL?
fuente
Una buena pieza que me ayuda al comenzar con C (Tomado de la Programación Expert C de Linden)
El One 'l' nul y The Two 'l' null
Memorice esta pequeña rima para recordar la terminología correcta para punteros y ASCII cero:
El carácter ASCII con el patrón de bits cero se denomina "NUL". El valor del puntero especial que significa que el puntero no apunta a ninguna parte es "NULL". Los dos términos no son intercambiables en significado.
fuente
NUL
es un código de control, tales comoBEL
,VT
,HT
,SOT
etc, y por lo tanto tiene un máximo. 3 personajes"NUL" no es 0, pero se refiere al carácter ASCII NUL. Al menos, así es como lo he visto usar. El puntero nulo a menudo se define como 0, pero esto depende del entorno en el que se esté ejecutando y la especificación de cualquier sistema operativo o idioma que esté utilizando.
En ANSI C, el puntero nulo se especifica como el valor entero 0. Por lo tanto, cualquier mundo donde eso no sea cierto no cumple con ANSI C.
fuente
Un byte con un valor de
0x00
es, en la tabla ASCII, el carácter especial llamadoNUL
oNULL
. En C, dado que no debe incrustar caracteres de control en su código fuente, esto se representa en cadenas C con un 0 escapado, es decir,\0
.Pero un verdadero NULL no es un valor. Es la ausencia de un valor. Para un puntero, significa que el puntero no tiene nada que señalar. En una base de datos, significa que no hay valor en un campo (que no es lo mismo que decir que el campo está en blanco, 0 o lleno de espacios).
El valor real que utiliza un determinado sistema o formato de archivo de base de datos para representar a
NULL
no es necesariamente0x00
.fuente
NULL
no se garantiza que sea 0; su valor exacto depende de la arquitectura. La mayoría de las arquitecturas principales lo definen(void*)0
.'\0'
siempre será igual a 0, porque así es como se codifica el byte 0 en un carácter literal.No recuerdo si se requieren los compiladores de C para uso ASCII - si no,
'0'
no siempre podría ser igual a 48. En cualquier caso, es poco probable que alguna vez encuentra un sistema que utiliza un juego de caracteres alternativo como EBCDIC a menos que esté trabajando muy sistemas oscurosLos tamaños de los distintos tipos diferirán en los sistemas de 64 bits, pero los valores enteros serán los mismos.
Algunos comentaristas han expresado dudas de que NULL sea igual a 0, pero no sea cero. Aquí hay un programa de ejemplo, junto con la salida esperada en dicho sistema:
Ese programa podría imprimir:
fuente
(nulo *) 0 es NULL y '\ 0' representa el final de una cadena.
fuente