Tại sao NULL không được khai báo?


87

Tôi gặp sự cố với trình tạo cấu trúc này khi tôi cố gắng biên dịch mã này:

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

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

khi tôi đến, lỗi này xảy ra:

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

Vấn đề cuối cùng là cấu trúc, nhưng nó hoạt động tốt khi nó ở trong main.cpp của tôi, lần này nó nằm trong tệp tiêu đề và đang gây ra cho tôi vấn đề này. Tôi đang sử dụng Code :: Blocks để biên dịch mã này

Câu trả lời:


139

NULLkhông phải là hằng số tích hợp sẵn trong ngôn ngữ C hoặc C ++. Trên thực tế, trong C ++, nó ít nhiều đã lỗi thời, 0thay vào đó chỉ cần sử dụng một chữ đơn giản , trình biên dịch sẽ làm đúng tùy theo ngữ cảnh.

Trong C ++ mới hơn (C ++ 11 trở lên), hãy sử dụng nullptr(như đã chỉ ra trong nhận xét, cảm ơn).

Nếu không, hãy thêm

#include <stddef.h>

để có được NULLđịnh nghĩa.


7
NULL là một phần của stddef.h, không phải stdlib.h. Về mặt kỹ thuật, bạn không được đảm bảo sẽ có được nó như một phần của stdlib.h mặc dù tôi thừa nhận sẽ khá ngạc nhiên nếu bạn không làm như vậy.
CB Bailey

8
NULL được định nghĩa trong các tiêu đề C sau: stddef.h, stdlib.h, stdio.h, locale.h, string.h và time.h (và wchar.h nếu bạn đếm C99).
Michael Burr

8
<cstddef>là tùy chọn sạch hơn.
Fred Foo

29
KHÔNG sử dụng "0" khi bạn có nghĩa là "NULL"! Có một sự khác biệt : ngữ nghĩa. Đừng bao giờ đánh giá thấp tầm quan trọng của việc biết điều gì đó là gì và sử dụng từ phù hợp, ngay cả khi trình biên dịch sẽ cho phép bạn xử lý nó!
imallett,

13
@ 6502 Không nói về điều đó; 0 và NULL luôn có cùng một giá trị (hầu như), vì vậy việc sử dụng '\ 0' hoặc 0 sẽ vô tình hoạt động. Vấn đề là ngữ nghĩa. Sử dụng NULL biểu cảm hơn, vì nó nói rằng giá trị là câu hỏi là một con trỏ, không chỉ là một số nguyên.
imallett,

34

Sử dụng NULL. Dù sao thì nó cũng chỉ là # được định nghĩa là 0 và nó rất hữu ích để phân biệt nó với số nguyên 0 về mặt ngữ nghĩa.

Có vấn đề với việc sử dụng 0 (và do đó NULL). Ví dụ:

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

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

Phiên bản tiếp theo của C ++ (C ++ 0x) bao gồm nullptrđể sửa lỗi này.

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

5
Nó được định nghĩa là ((void *)0)bởi hầu hết các triển khai thư viện tiêu chuẩn C.
Triang3l,

1
Đây là câu trả lời ngắn gọn hay nhất (và chính xác về mặt kỹ thuật) mà tôi từng đọc về chủ đề: NULL so với 0 so với nullptr. Cảm ơn bạn!
jose.angel.jimenez

2
@SiPlus ((void *)0)không chính xác trong C ++, vì void*không thể cưỡng chế các loại con trỏ khác như trong C. glibc, chẳng hạn, thực hiện #define NULL 0khi __cplusplusđược định nghĩa.
rpjohnst

16

NULLkhông phải là một phần bản địa của ngôn ngữ C ++ cốt lõi, nhưng nó là một phần của thư viện chuẩn. Bạn cần bao gồm một trong các tệp tiêu đề chuẩn bao gồm định nghĩa của nó. #include <cstddef>hoặc #include <stddef.h>phải đủ.

Định nghĩa của NULLđược đảm bảo sẽ có sẵn nếu bạn bao gồm cstddefhoặc stddef.h. Nó không được đảm bảo, nhưng bạn rất có thể nhận được định nghĩa của nó nếu bạn bao gồm nhiều tiêu đề tiêu chuẩn khác.


12

Bạn có bao gồm "stdlib.h" hoặc "cstdlib" trong tệp này không? NULL được định nghĩa trong stdlib.h / cstdlib

#include <stdlib.h>

hoặc là

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

2
NULL là một phần của stddef.h, không stdlib.h
awiebe

@awiebe Đó là những gì tôi nghĩ cho đến năm phút trước - theo C99, khá nhiều tệp tiêu đề khác nhau phải xác định nó. Phần 7.17 yêu cầu stddef.h đến, 7.20 yêu cầu nó trong stdlib.h, và có thể có một vài phần khác tốt.
AJM-Reinstate-Monica

4

Không sử dụng NULL, C ++ cho phép bạn sử dụng không trang trí 0thay thế:

previous = 0;
next = 0;

Và, như ở C ++ 11, bạn thường không nên sử dụng một trong hai NULL hoặc 0 vì nó cung cấp cho bạn nullptrkiểu std::nullptr_tphù hợp hơn với tác vụ.


33
Tôi có xu hướng nghĩ rằng NULL là tài liệu hữu ích mà bạn đang có ý định sử dụng hằng số con trỏ null thay vì hằng số nguyên, mặc dù tôi không phản đối việc sử dụng 0. Tôi thừa nhận rằng bạn không đạt được bất kỳ lợi ích thiết thực nào vào lúc này , nhưng nếu / khi bạn áp dụng phiên bản C ++ tiếp theo, nó sẽ mang lại một khởi đầu tốt cho những nơi thay đổi để sử dụng hằng số nullptr mới.
CB Bailey

1
tôi đồng ý với cả hai bạn, tất nhiên. Ngẫu nhiên, thật tốt khi một tài liệu sử dụng một con trỏ, nhưng cũng tốt cho một tài liệu mà người ta thực sự đặt một số nguyên về phía trước. xét printf ("% p \ n", NULL); // OH, UB. Hoặc nếu bạn có hai quá tải, void f (int); void f (void *); bạn có thể nghĩ rằng f (NULL); gọi phiên bản void * khi xem nhanh cuộc gọi. f (0); sẽ ghi lại thực tế là nó sẽ thực sự gọi phiên bản int, nhưng sẽ không ghi lại thực tế là bạn có ý định bạn vượt qua một con trỏ :( Tốt mà nullptr sửa nó :)
Johannes Schaub - litb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.