Dlaczego wartość NULL jest niezadeklarowana?

87

Mam problem z tym konstruktorem struktury, gdy próbuję skompilować ten kod:

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

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

kiedy przychodzę pojawia się ten błąd:

\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 ===|

Ostatnim problemem była struktura, ale działała dobrze, gdy znajdowała się w moim main.cpp, tym razem jest w pliku nagłówkowym i daje mi ten problem. Do kompilacji tego kodu używam Code :: Blocks

rozwijać
źródło

Odpowiedzi:

139

NULLnie jest stałą wbudowaną w językach C lub C ++. W rzeczywistości w C ++ jest to mniej lub bardziej przestarzałe, 0zamiast tego użyj zwykłego literału , kompilator zrobi właściwą rzecz w zależności od kontekstu.

W nowszych wersjach C ++ (C ++ 11 i wyższych) użyj nullptr(jak wskazano w komentarzu, dzięki).

W przeciwnym razie dodaj

#include <stddef.h>

aby uzyskać NULLdefinicję.

rozwijać
źródło
7
NULL jest częścią stddef.h, a nie stdlib.h. Technicznie rzecz biorąc, nie masz gwarancji, że dostaniesz go jako część stdlib.h, chociaż przyznaję, że byłoby to dość zaskakujące, gdybyś tego nie zrobił.
CB Bailey
8
Wartość NULL jest zdefiniowana w następujących nagłówkach C: stddef.h, stdlib.h, stdio.h, locale.h, string.h i time.h (i wchar.h, jeśli policzysz C99).
Michael Burr
8
<cstddef>to czystsza opcja.
Fred Foo
29
NIE UŻYWAJ „0”, gdy masz na myśli „NULL”! Jest różnica : semantyka. Nigdy nie lekceważ, jak ważne jest, aby wiedzieć, co to jest i używać właściwego słowa, nawet jeśli kompilator pozwoli ci ujść na sucho!
imallett,
13
@ 6502 Nie mówię o tym; 0 i NULL mają tę samą wartość (prawie) zawsze, więc użycie '\ 0' lub 0 będzie przypadkowo działać. Problemem jest semantyka. Używanie NULL jest bardziej wyraziste, ponieważ mówi, że wartość jest pytaniem jest wskaźnikiem, a nie tylko liczbą całkowitą.
imallett
34

Używaj NULL. To jest po prostu #definiowane jako 0 i tak jest bardzo przydatne do semantycznego odróżnienia go od liczby całkowitej 0.

Występują problemy z używaniem 0 (i stąd NULL). Na przykład:

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

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

Następna wersja C ++ (C ++ 0x) zawiera nullptrrozwiązanie tego problemu.

f(nullptr); // Calls f(void*).
Eric
źródło
5
Jest zdefiniowany tak, jak ((void *)0)w większości implementacji standardowych bibliotek C.
Triang3l
1
To najlepsza krótka odpowiedź (i technicznie precyzyjna), jaką kiedykolwiek czytałem na ten temat: NULL vs. 0 vs. nullptr. Dziękuję Ci!
jose.angel.jimenez
2
@SiPlus ((void *)0)jest niepoprawny w C ++, ponieważ void*nie jest konwertowany do innych typów wskaźników, tak jak w C. glibc, na przykład, #define NULL 0gdy __cplusplusjest zdefiniowany.
rpjohnst
16

NULLnie jest natywną częścią podstawowego języka C ++, ale jest częścią standardowej biblioteki. Musisz dołączyć jeden ze standardowych plików nagłówkowych, które zawierają jego definicję. #include <cstddef>lub #include <stddef.h>powinno wystarczyć.

Definicja z NULLpewnością będzie dostępna, jeśli dołączysz cstddeflub stddef.h. Nie jest to gwarantowane, ale jest bardzo prawdopodobne, że zostanie dołączona jego definicja, jeśli zamiast tego dołączysz wiele innych standardowych nagłówków.

CB Bailey
źródło
12

Czy dołączasz „stdlib.h” lub „cstdlib” do tego pliku? NULL jest zdefiniowany w stdlib.h / cstdlib

#include <stdlib.h>

lub

#include <cstdlib>  // This is preferrable for c++
Andy White
źródło
2
NULL jest częścią stddef.h, a nie stdlib.h
awiebe
@awiebe Tak myślałem jeszcze pięć minut temu - według C99 kilka różnych plików nagłówkowych musi to zdefiniować. Sekcja 7.17 wymaga stddef.h do, 7.20 wymaga tego w stdlib.h, a jest prawdopodobnie kilka innych.
AJM-Reinstate-Monica
4

Nie używaj NULL, C ++ pozwala 0zamiast tego używać nie zdobionych :

previous = 0;
next = 0;

I podobnie jak w C ++ 11, generalnie nie powinieneś używać żadnego z nich NULL lub 0 ponieważ zapewnia on nullptrtyp std::nullptr_t, który jest lepiej dopasowany do zadania.

paxdiablo
źródło
33
Wydaje mi się, że NULL jest użyteczną dokumentacją, że zamierzasz użyć stałej wskaźnika zerowego zamiast stałej całkowitej, chociaż nie sprzeciwiam się użyciu 0. Przyznam, że w tej chwili nie uzyskasz żadnych praktycznych korzyści , ale jeśli / kiedy przyjmiesz następną wersję C ++, będzie to dobry początek dla miejsc do zmiany, aby użyć nowej stałej nullptr.
CB Bailey
1
oczywiście zgadzam się z wami obojgiem. Nawiasem mówiąc, dobrze jest, że jeden dokument używa wskaźnika, ale także dobrze jest dokumentować, że faktycznie przesuwa się liczbę całkowitą do przodu. rozważ printf ("% p \ n", NULL); // OH, UB. Lub jeśli masz dwa przeciążenia, void f (int); nieważne f (nieważne *); możesz pomyśleć, że f (NULL); wywołuje wersję void *, sprawdzając połączenie. f (0); udokumentuje fakt, że faktycznie wywoła wersję int, ale nie udokumentuje faktu, że zamierzasz przekazać wskaźnik :( Dobrze, że nullptr to naprawia :)
Johannes Schaub - litb