Чому NULL не оголошено?


87

У мене проблема з цим конструктором структури, коли я намагаюся скомпілювати цей код:

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

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

коли я приходжу, виникає ця помилка:

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

Останньою проблемою була структура, але вона працювала нормально, коли була в моєму main.cpp, на цей раз вона знаходиться у заголовковому файлі і видає мені цю проблему. Я використовую Code :: Blocks для компіляції цього коду

Відповіді:


139

NULLне є вбудованою константою в мовах C або C ++. Насправді, в C ++ він більш-менш застарів, просто використовуйте 0замість нього звичайний літерал , компілятор вчинить правильно, залежно від контексту.

У новіших версіях C ++ (C ++ 11 і вище) використовуйте nullptr(як зазначено в коментарі, спасибі).

В іншому випадку додайте

#include <stddef.h>

щоб отримати NULLвизначення.


7
NULL є частиною stddef.h, а не stdlib.h. Технічно ви не гарантовано отримаєте його як частину stdlib.h, хоча я визнаю, що це було б досить вражаюче, якби ви цього не зробили.
CB Bailey

8
NULL визначається у таких заголовках C: stddef.h, stdlib.h, stdio.h, locale.h, string.h та time.h (і wchar.h, якщо рахувати C99).
Michael Burr

8
<cstddef>є чистішим варіантом.
Фред Фу

29
НЕ використовуйте "0", коли ви маєте на увазі "НУЛЬ"! Є різниця : семантика. Ніколи не недооцінюйте важливості знати, що щось є, і вживати правильне слово, навіть якщо компілятор дозволить вам уникнути цього!
imallett

13
@ 6502 Не кажу про це; 0 і NULL мають одне і те ж значення (майже) завжди, тому використання \ \ 0 або 0 випадково спрацює. Проблема полягає в семантиці. Використання NULL є більш виразним, оскільки в ньому сказано, що значення питання - це вказівник, а не просто ціле число.
imallett

34

Використовуйте NULL. Це так чи інакше # визначається як 0, і дуже корисно семантично відрізнити його від цілого числа 0.

Є проблеми з використанням 0 (а отже, і NULL). Наприклад:

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

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

Наступна версія C ++ (C ++ 0x) включає nullptrце виправлення.

f(nullptr); // Calls f(void*).

5
Це визначається як ((void *)0)у більшості реалізацій стандартної бібліотеки C.
Triang3l

1
Це найкраща коротка відповідь (і технічно точна), яку я коли-небудь читав стосовно теми: NULL проти 0 проти nullptr. Дякую!
jose.angel.jimenez

2
@SiPlus ((void *)0)неправильний у C ++, оскільки void*не примусовий до інших типів покажчиків, як це робиться, наприклад, у C. glibc, #define NULL 0коли __cplusplusце визначено.
rpjohnst

16

NULLне є рідною частиною основної мови C ++, але є частиною стандартної бібліотеки. Вам потрібно включити один із стандартних файлів заголовків, що включає його визначення. #include <cstddef>або #include <stddef.h>має бути достатнім.

Визначення слова NULLгарантовано буде доступним, якщо ви включите cstddefабо stddef.h. Це не гарантовано, але ви, швидше за все, включите його визначення, якщо замість цього включите багато інших стандартних заголовків.


12

Ви включаєте "stdlib.h" або "cstdlib" у цей файл? NULL визначено в stdlib.h / cstdlib

#include <stdlib.h>

або

#include <cstdlib>  // This is preferrable for c++

2
NULL є частиною stddef.h, а не stdlib.h
awiebe

@awiebe Це було те, про що я думав ще п’ять хвилин тому - згідно з C99, це має визначати досить багато різних заголовкових файлів. Розділ 7.17 вимагає stddef.h до, 7.20 вимагає цього в stdlib.h, і є, мабуть, ще кілька хороших.
AJM-Reinstate-Monica

4

Не використовуйте NULL, C ++ дозволяє 0замість цього використовувати без прикрас :

previous = 0;
next = 0;

І, як і в C ++ 11, ви, як правило, не повинні використовувати ні те, ні NULL інше, 0 оскільки воно надає вам nullptrтип std::nullptr_t, який краще підходить для завдання.


33
Я вважаю, що NULL є корисною документацією про те, що ви маєте намір використовувати константу нульового вказівника, а не цілу константу, хоча я не заперечую проти використання 0. Признаю, що на даний момент ви не отримуєте ніяких практичних переваг , але якщо / коли ви приймаєте наступну версію C ++, це дає гарний старт місцям, де потрібно змінити використання нової константи nullptr.
CB Bailey

1
я згоден з вами обома, звичайно. До речі, добре і те, що в одному документі використовується покажчик, але також добре, що документується, що насправді виводиться ціле число вперед. розглянемо printf ("% p \ n", NULL); // OH, UB. Або якщо у вас є дві перевантаження, void f (int); void f (void *); ви можете подумати, що f (NULL); викликає версію void * під час швидкого перегляду дзвінка. f (0); зафіксує той факт, що він фактично буде викликати версію int, але не зафіксує той факт, що ви маєте намір передавати вказівник :( Добре, що nullptr це виправляє :)
Йоханнес Шауб - litb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.