¿Por qué no se declara NULL?

87

Tengo un problema con este constructor de estructuras cuando intento compilar este código:

typedef struct Node
{
    Node( int data ) //
    {
        this->data = data;
        previous = NULL; // Compiler indicates here
        next = NULL;
    }

    int data;
    Node* previous;
    Node* next;
} NODE;

cuando vengo se produce este error:

\linkedlist\linkedlist.h||In constructor `Node::Node(int)':|
\linkedlist\linkedlist.h|9|error: `NULL' was not declared in this scope|
    ||=== Build finished: 1 errors, 0 warnings ===|

El último problema fue la estructura, pero funcionó bien cuando estaba en mi main.cpp, esta vez está en un archivo de encabezado y me está dando este problema. Estoy usando Code :: Blocks para compilar este código

relajarse
fuente

Respuestas:

139

NULLno es una constante incorporada en los lenguajes C o C ++. De hecho, en C ++ es más o menos obsoleto, simplemente use un literal simple en su 0lugar, el compilador hará lo correcto según el contexto.

En C ++ más reciente (C ++ 11 y superior), use nullptr(como se señaló en un comentario, gracias).

De lo contrario, agregue

#include <stddef.h>

para obtener la NULLdefinición.

relajarse
fuente
7
NULL es parte de stddef.h, no stdlib.h. Técnicamente, no está garantizado que lo obtenga como parte de stdlib.h, aunque admito que sería bastante sorprendente si no lo hiciera.
CB Bailey
8
NULL se define en los siguientes encabezados de C: stddef.h, stdlib.h, stdio.h, locale.h, string.hy time.h (y wchar.h si cuenta C99).
Michael Burr
8
<cstddef>es la opción más limpia.
Fred Foo
29
¡NO use "0" cuando quiera decir "NULO"! Hay una diferencia : semántica. Nunca subestimes la importancia de saber qué es algo y usar la palabra correcta, ¡incluso si el compilador te permite salirte con la tuya!
imallett
13
@ 6502 No hablo de eso; 0 y NULL tienen el mismo valor (casi) siempre, por lo que usar '\ 0' o 0 funcionará accidentalmente. El problema es la semántica. Usar NULL es más expresivo, ya que dice que el valor de la pregunta es un puntero, no solo un número entero.
imallett
34

Utilice NULL. De todos modos, está #definido como 0 y es muy útil distinguirlo semánticamente del entero 0.

Hay problemas con el uso de 0 (y por lo tanto NULL). Por ejemplo:

void f(int);
void f(void*);

f(0); // Ambiguous. Calls f(int).

La próxima versión de C ++ (C ++ 0x) incluye nullptrpara solucionar este problema.

f(nullptr); // Calls f(void*).
Eric
fuente
5
Está definido ((void *)0)por la mayoría de las implementaciones de bibliotecas estándar de C.
Triang3l
1
Esta es la mejor respuesta corta (y técnicamente precisa) que he leído sobre el tema: NULL vs. 0 vs. nullptr. ¡Gracias!
jose.angel.jimenez
2
@SiPlus ((void *)0)es incorrecto en C ++, porque void*no es coercible a otros tipos de punteros como lo es en C. glibc, por ejemplo, #define NULL 0cuando __cplusplusse define.
rpjohnst
16

NULLno es una parte nativa del lenguaje central C ++, pero es parte de la biblioteca estándar. Debe incluir uno de los archivos de encabezado estándar que incluyen su definición. #include <cstddef>o #include <stddef.h>debería ser suficiente.

Se NULLgarantiza que la definición de estará disponible si incluye cstddefo stddef.h. No está garantizado, pero es muy probable que incluya su definición si incluye muchos de los otros encabezados estándar.

CB Bailey
fuente
12

¿Está incluyendo "stdlib.h" o "cstdlib" en este archivo? NULL está definido en stdlib.h / cstdlib

#include <stdlib.h>

o

#include <cstdlib>  // This is preferrable for c++
Andy White
fuente
2
NULL es parte de stddef.h, no stdlib.h
awiebe
@awiebe Eso era lo que pensaba hasta hace cinco minutos: según C99, bastantes archivos de encabezado diferentes tienen que definirlo. La sección 7.17 requiere stddef.h, la 7.20 lo requiere en stdlib.h, y probablemente haya algunos otros.
AJM-Reinstate-Monica
4

No lo use NULL, C ++ le permite usar lo sin adornos en su 0lugar:

previous = 0;
next = 0;

Y, al igual que en C ++ 11, por lo general no debería utilizar ni NULL o, 0 ya que le proporciona un nullptrtipo std::nullptr_t, que se adapta mejor a la tarea.

paxdiablo
fuente
33
Tiendo a pensar que NULL es documentación útil de que tiene la intención de usar una constante de puntero nulo en lugar de una constante entera, aunque no me opongo a usar 0. Admito que no obtiene ningún beneficio práctico en este momento , pero si / cuando adopta la próxima versión de C ++, da un buen comienzo para que los lugares cambien para usar la nueva constante nullptr.
CB Bailey
1
Estoy de acuerdo con los dos, por supuesto. Por cierto, es bueno que uno documente que uno usa un puntero, pero también es bueno que documente que uno realmente presenta un número entero. considere printf ("% p \ n", NULL); // OH, UB. O si tiene dos sobrecargas, void f (int); void f (vacío *); podría pensar que f (NULL); llama a la versión void * al echar un vistazo rápido a la llamada. f (0); documentará el hecho de que realmente llamará a la versión int, pero no documentará el hecho de que tiene la intención de pasar un puntero :( Es bueno que nullptr lo arregle :)
Johannes Schaub - litb