เหตุใดจึงไม่มีการประกาศ 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>เป็นตัวเลือกที่สะอาดกว่า
Fred Foo

30
อย่าใช้ "0" เมื่อคุณหมายถึง "NULL"! มีความแตกต่าง : ความหมาย อย่าประมาทความสำคัญของการรู้ว่าอะไรคืออะไรและใช้คำที่ถูกต้องแม้ว่าคอมไพเลอร์จะทำให้คุณหนีไปได้!
imallett

13
@ 6502 ไม่ได้พูดถึงนะ; 0 และ NULL มีค่าเท่ากัน (เกือบ) เสมอดังนั้นการใช้ "\ 0" หรือ 0 จะทำงานโดยไม่ได้ตั้งใจ ปัญหาคือความหมาย การใช้ NULL นั้นแสดงออกได้ชัดเจนกว่าเนื่องจากมีการบอกว่าค่าเป็นคำถามเป็นตัวชี้ไม่ใช่แค่จำนวนเต็ม
imallett

35

ใช้ 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

อย่าใช้NULLC ++ ช่วยให้คุณใช้สิ่งที่ไม่ได้ตกแต่ง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); // โอ้อุ๊บ. หรือถ้าคุณมีโอเวอร์โหลดสองครั้งให้โมฆะ f (int); เป็นโมฆะ f (โมฆะ *); คุณอาจคิดว่า f (NULL); เรียกเวอร์ชันโมฆะ * เมื่อดูการโทรอย่างรวดเร็ว ฉ (0); จะบันทึกข้อเท็จจริงที่ว่ามันจะเรียกเวอร์ชัน int จริง แต่จะไม่บันทึกข้อเท็จจริงที่ว่าคุณตั้งใจจะส่งตัวชี้ :( ดีที่ nullptr แก้ไขได้ :)
Johannes Schaub - litb
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.