Por que NULL não é declarado?

87

Tenho um problema com este construtor de estrutura quando tento 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;

quando eu venho este erro ocorre:

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

O último problema foi a estrutura, mas funcionou bem quando estava no meu main.cpp, desta vez está em um arquivo de cabeçalho e está me causando esse problema. Estou usando Code :: Blocks para compilar este código

desanuviar
fonte

Respostas:

139

NULLnão é uma constante embutida nas linguagens C ou C ++. Na verdade, em C ++ é mais ou menos obsoleto, apenas use um literal simples 0, o compilador fará a coisa certa dependendo do contexto.

No C ++ mais recente (C ++ 11 e superior), use nullptr(conforme indicado em um comentário, obrigado).

Caso contrário, adicione

#include <stddef.h>

para obter a NULLdefinição.

desanuviar
fonte
7
NULL faz parte de stddef.h, não stdlib.h. Tecnicamente, você não tem garantia de obtê-lo como parte do stdlib.h, embora eu admita que seria muito surpreendente se não o fizesse.
CB Bailey
8
NULL é definido nos seguintes cabeçalhos C: stddef.h, stdlib.h, stdio.h, locale.h, string.h e time.h (e wchar.h se você contar C99).
Michael Burr
8
<cstddef>é a opção mais limpa.
Fred Foo
29
NÃO use "0" quando você quer dizer "NULL"! Existe uma diferença : semântica. Nunca subestime a importância de saber o que é algo e usar a palavra certa, mesmo que o compilador deixe você se safar!
imallett
13
@ 6502 Não estou falando sobre isso; 0 e NULL têm o mesmo valor (quase) sempre, então usar '\ 0' ou 0 funcionará acidentalmente. O problema é a semântica. Usar NULL é mais expressivo, pois diz que o valor em questão é um ponteiro, não apenas um inteiro.
imallett
34

Use NULL. É apenas #definido como 0 e é muito útil diferenciá-lo semanticamente do inteiro 0.

Existem problemas com o uso de 0 (e, portanto, NULL). Por exemplo:

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

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

A próxima versão do C ++ (C ++ 0x) inclui nullptrpara corrigir isso.

f(nullptr); // Calls f(void*).
Eric
fonte
5
É definido como ((void *)0)pela maioria das implementações de biblioteca C padrão.
Triang3l
1
Esta é a melhor resposta curta (e tecnicamente precisa) que já li sobre o tópico: NULL vs. 0 vs. nullptr. Obrigado!
jose.angel.jimenez
2
@SiPlus ((void *)0)está incorreto em C ++, porque void*não é coercível para outros tipos de ponteiro da mesma forma que em C. glibc, por exemplo, faz #define NULL 0quando __cplusplusé definido.
rpjohnst
16

NULLnão é uma parte nativa da linguagem C ++ principal, mas faz parte da biblioteca padrão. Você precisa incluir um dos arquivos de cabeçalho padrão que incluem sua definição. #include <cstddef>ou #include <stddef.h>deve ser suficiente.

A definição de NULLestará disponível se você incluir cstddefou stddef.h. Não é garantido, mas é muito provável que sua definição seja incluída se incluir muitos dos outros cabeçalhos padrão.

CB Bailey
fonte
12

Você está incluindo "stdlib.h" ou "cstdlib" neste arquivo? NULL é definido em stdlib.h / cstdlib

#include <stdlib.h>

ou

#include <cstdlib>  // This is preferrable for c++
Andy White
fonte
2
NULL é parte de stddef.h, não stdlib.h
awiebe de
@awiebe Isso era o que eu pensava até cinco minutos atrás - de acordo com o C99, vários arquivos de cabeçalho diferentes precisam definir isso. A seção 7.17 requer stddef.h para, 7.20 requer em stdlib.h, e provavelmente há alguns outros.
AJM-Reinstate-Monica
4

Não use NULL, C ++ permite que você use o sem adornos em seu 0lugar:

previous = 0;
next = 0;

E, como em C ++ 11, você geralmente não deve ser usando NULL ou 0 , uma vez que fornece nullptrdo tipo std::nullptr_t, o que é mais adequado para a tarefa.

paxdiablo
fonte
33
Eu tendo a pensar que NULL é uma documentação útil que você pretende usar uma constante de ponteiro nulo em vez de uma constante de inteiro, embora eu não me oponha ao uso de 0. Admito que você não ganha nenhum benefício prático no momento , mas se / quando você adotar a próxima versão C ++, isso dará um bom começo para que os lugares mudem para usar a nova constante nullptr.
CB Bailey
1
concordo com vocês dois, é claro. A propósito, é bom que se documente o uso de um ponteiro, mas também é bom documentar que realmente se coloca um inteiro à frente. considere printf ("% p \ n", NULL); // OH, UB. Ou se você tiver duas sobrecargas, void f (int); vazio f (vazio *); você pode pensar que f (NULL); chama a versão void * ao dar uma olhada rápida na chamada. f (0); documentará o fato de que ele realmente chamará a versão int, mas não documentará o fato de que você pretende passar um ponteiro :( Bom, porque nullptr corrige isso :)
Johannes Schaub - litb