ความแตกต่างระหว่างตัวชี้ที่ชี้ไปยังตำแหน่ง 0x0 และตัวชี้ถูกตั้งค่าเป็น NULL คืออะไร


12

ตัวชี้ชี้ไปที่ 0x0000 เหมือนกับตัวชี้ที่ตั้งค่าเป็น NULL หรือไม่ ถ้าค่า NULL ถูกกำหนดในภาษา C แปลตำแหน่งทางกายภาพเป็นอะไร มันเหมือนกับ 0x0000 ฉันจะหารายละเอียดเพิ่มเติมเกี่ยวกับแนวคิดเหล่านี้ได้ที่ไหน


1
นี้ได้ถูกถามเกี่ยวกับกองมากเกิน - stackoverflow.com/questions/1296843/... ฉันคิดว่ามันเป็นเส้นเขตแดนสำหรับเรา แต่ฉันยินดีที่จะให้ประโยชน์กับข้อสงสัยในขณะนั้น
ChrisF

คำตอบ:


12

จุดที่คำตอบส่วนใหญ่ที่นี่ไม่ได้กล่าวถึงอย่างน้อยก็ไม่ชัดเจนก็คือตัวชี้ nullเป็นค่าที่มีอยู่ระหว่างการดำเนินการและค่าคงที่ตัวชี้โมฆะคือโครงสร้างประโยคที่มีอยู่ในซอร์สโค้ด C

คงชี้โมฆะเป็นคำตอบที่ถูกต้อง Karlson ของรัฐเป็นทั้งการแสดงออกจำนวนเต็มอย่างต่อเนื่องกับค่า 0 (ง่าย0เป็นตัวอย่างที่พบมากที่สุด) หรือดังกล่าวแสดงออกถึงความหล่อvoid*(เช่น(void*)0)

NULLเป็นแมโครที่กำหนดไว้ใน<stddef.h>หลายส่วนหัวมาตรฐานอื่น ๆ ที่จะขยายไปสู่การดำเนินการกำหนดตัวชี้โมฆะคงที่ โดยทั่วไปแล้วการขยายตัวเป็นอย่างใดอย่างหนึ่ง0หรือ((void*)0)(จำเป็นต้องใช้วงเล็บด้านนอกเพื่อตอบสนองกฎภาษาอื่น ๆ )

ดังนั้นตามตัวอักษร0เมื่อใช้ในบริบทที่ต้องการนิพจน์ชนิดพอยน์เตอร์จะประเมินค่าเสมอnull pointerคือค่าพอยน์เตอร์เฉพาะที่ชี้ไปที่วัตถุใด ๆ แต่นั่นไม่ได้หมายความถึงอะไรเกี่ยวกับการเป็นตัวแทนของการชี้โมฆะ พอยน์เตอร์พอยน์เตอร์นั้นมักใช้แทนค่าเป็นบิตทั้งหมด แต่มันสามารถถูกแทนด้วยอะไรก็ได้ แต่ถึงแม้ว่าตัวชี้โมฆะจะแสดงเป็น0xDEADBEEF, 0หรือ(void*)0ยังคงมีอย่างต่อเนื่องชี้โมฆะ

คำตอบสำหรับคำถามเกี่ยวกับ stackoverflowครอบคลุมถึงสิ่งนี้

สิ่งนี้บ่งบอกถึงสิ่งอื่น ๆ ที่memset()หรือcalloc()ซึ่งสามารถตั้งค่าขอบเขตของหน่วยความจำเป็น all-bits-zero ไม่จำเป็นต้องตั้งค่าพอยน์เตอร์ใด ๆ ในภูมิภาคนั้นเป็นพอยน์เตอร์พอยน์เตอร์ พวกเขามีแนวโน้มที่จะทำเช่นนั้นในการใช้งานส่วนใหญ่ แต่ภาษาไม่รับประกัน

ผมไม่ทราบว่าทำไมคำถามนี้จะไม่ถือว่าเป็นซ้ำของคนนี้หรือว่ามันเป็นเฉพาะที่นี่


1
หนึ่งใน peeves ของฉันกับการออกแบบและวิวัฒนาการของ C คือเลขศูนย์ยังคงถูกใช้เพื่อเป็นตัวแทนพอยน์เตอร์โมฆะ ย้อนกลับไปในช่วงแรก ๆ ของภาษา (เช่นก่อนการปรากฎของสิ่งต่าง ๆ เช่นฟังก์ชั่นต้นแบบ) พอยน์เตอร์และจำนวนเต็มสามารถใช้แทนกันได้อย่างเพียงพอว่าการใช้ "0" สำหรับตัวชี้โมฆะนั้นง่ายมาก เมื่อจำเป็นต้องแยกแยะความแตกต่างระหว่างจำนวนศูนย์จำนวนเต็มและตัวชี้โมฆะอย่างไรก็ตามการแทนค่า "0" ควรถูกคัดค้านด้วยคำสำคัญหรือลำดับการดำเนินการ
supercat

นี่หมายความว่าตัวชี้ NULL อาจชี้ไปที่ตำแหน่งจริง ๆ เมื่อกำหนด NULL ขึ้นอยู่กับแพลตฟอร์มหรือไม่ ตัวชี้โมฆะคงที่อาจสร้างโครงสร้างประโยค แต่จะเกิดอะไรขึ้นเมื่อโค้ดทำงาน? สมมติว่าโครงสร้างประโยคนี้ได้รับการคอมไพล์บนแพลตฟอร์ม GNU / Linux ค่าตัวชี้คืออะไรเมื่อเรากำหนดค่า NULL ให้กับมัน? ที่อยู่นี้แตกต่างจากที่อยู่อื่นอย่างไร
Arpith

1
@Arpith: การกำหนดNULLหรือใด ๆคงชี้โมฆะเพื่อชี้วัตถุชุดว่ามูลค่าของวัตถุไปชี้โมฆะ ในระดับเครื่องมันอาจชี้ไปที่หน่วยความจำที่ถูกต้อง การอ้างอิงตัวชี้ null มีลักษณะการทำงานที่ไม่ได้กำหนด การเข้าถึงหน่วยความจำที่แอดเดรส0x0000000เป็นพฤติกรรมที่ถูกต้องเช่นเดียวกับสิ่งอื่น ที่อยู่นั้นแตกต่างจากที่อยู่อื่น ๆ โดย (a) เปรียบเทียบเท่ากับNULLและ (b) เปรียบเทียบไม่เท่ากันกับตัวชี้ใด ๆ กับวัตถุ C ตัวชี้ null เป็นพลชี้ค่าใช้เพื่อบ่งชี้ว่ามันไม่ได้ชี้ไปที่ใด
Keith Thompson

1
ในระดับเครื่องอาจชี้ไปที่หน่วยความจำที่ถูกต้อง แต่ในสภาพแวดล้อม C ส่วนใหญ่จะชี้ไปที่หน่วยความจำที่ไม่ถูกต้องดังนั้นความพยายามในการใช้ตัวชี้จะส่งผลให้เกิดกับดักฮาร์ดแวร์ / ความผิด / ข้อยกเว้น โดยปกติจะเป็นบนแพลตฟอร์มฮาร์ดแวร์ที่ง่ายที่สุดเท่านั้น --- ที่ไม่มีการสนับสนุนการจัดการหน่วยความจำ - โดยที่ตัวชี้ NULL ชี้ไปยังตำแหน่งหน่วยความจำที่ถูกต้อง
โซโลมอนช้า

7

ทุกแพลตฟอร์มออกมีอิสระในการกำหนด NULL ตามที่พอใจ

ตามมาตรฐาน C หากคุณกำหนดค่าศูนย์เป็นตัวชี้มันจะถูกแปลงเป็นค่า NULL (สำหรับแพลตฟอร์มนั้น) อย่างไรก็ตามหากคุณใช้ตัวชี้ NULL และส่งไปยัง int ไม่มีการรับประกันว่าคุณจะได้รับศูนย์ บนทุกแพลตฟอร์มที่นั่น ความจริงก็คือบนแพลตฟอร์มส่วนใหญ่มันจะเป็นศูนย์

ข้อมูลเกี่ยวกับสิ่งที่คุณจะพบในซีจำเพาะภาษา แหล่งข้อมูลหนึ่งความน่าเชื่อถือที่ฉันไม่สามารถรับรองได้คือ: http://www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf


2
NULL pointer constantถ้าพวกเขาเลือกที่จะหนีออกไปจากมาตรฐานที่พวกเขามีอิสระที่จะกำหนด เท่าที่ฉันรู้ไม่มีคอมไพเลอร์ออกมีที่ทำอย่างนั้น
Karlson

มีผู้แปลออกมีที่ไม่ใช้ NULL เป็น 0 หรือไม่ และเป็นโมฆะรับประกันว่าจะประเมินเป็นเท็จ?
ugoren

NULL รับประกันว่าจะประเมินผลเป็นเท็จตามมาตรฐาน ฉันไม่ทราบว่ามีคอมไพเลอร์ใด ๆ (แพลตฟอร์มจริง) ที่ไม่ได้ใช้ NULL เป็น 0 และฉันสงสัยอย่างจริงจัง แต่มาตรฐานไม่ได้ห้ามมันดังนั้นใครจะรู้
Mike Nakis

มีความสับสนระหว่างตัวแทนของนามธรรม "ชี้โมฆะคงที่" (ตามที่กล่าวไว้ในสเปค) ในหน่วยความจำซึ่งอาจจะเป็นประสงค์แพลตฟอร์มชงและความหมายของการเป็นNULLมาโครซึ่งมีการขยายตัวออกไป0ใน C ++ และทั้ง0หรือ(void *)0ใน C, เพราะนั่นคือของจริง "ค่าคงที่ตัวชี้โมฆะ"
ม.ค. Hudec

ในขณะที่ NULL สามารถอยู่ในทฤษฎีที่ถูกกำหนดเป็นอะไร แต่มีการรับประกันตามมาตรฐานที่ค่าคงที่ int ที่มีค่า 0 typecasted ไปยังตัวชี้จะส่งผลให้ตัวชี้โมฆะ (ISO 9899: 1999 6.3.2.3/3) แมโคร NULL ของ stddef.h ต้องเป็นตัวชี้ null (7.17 / 3) ดังนั้นจึงเป็นภาระที่มากสำหรับคอมไพเลอร์ที่จะไม่ใช้ NULL เป็น 0 หรือ (void *) 0

1

มันถูกกำหนดในภาษา C เพราะไม่มีที่อยู่เครื่องไม่เปลี่ยนแปลงใด ๆ ที่มันเท่ากับ ถ้าเป็นเช่นนั้นเราไม่จำเป็นต้องมีสิ่งที่เป็นนามธรรม! แม้ว่าในแพลตฟอร์มส่วนใหญ่แล้ว NULL อาจถูกนำมาใช้เป็น 0 ในบางประเภทหรืออื่น ๆ ในที่สุดมันก็ผิดที่คิดว่ามันเป็นสากลดังนั้นหากคุณสนใจเรื่องการพกพา


นั่นคือมาตรฐานสำหรับopen-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
Karlson

0

ตามส่วนเอกสารมาตรฐาน C6.3.2.3 :

นิพจน์ค่าคงที่จำนวนเต็มที่มีค่า 0 หรือนิพจน์ดังกล่าวที่พิมพ์เป็นโมฆะ * เรียกว่าค่าคงที่ตัวชี้โมฆะ 53) ถ้าค่าคงตัวตัวชี้โมฆะถูกแปลงเป็นประเภทตัวชี้ตัวชี้ผลลัพธ์จะเรียกว่าตัวชี้โมฆะคือ รับประกันว่าจะเปรียบเทียบไม่เท่ากันกับตัวชี้ไปยังวัตถุหรือฟังก์ชั่นใด ๆ

จนถึงตอนนี้ฉันยังไม่เห็นคอมไพเลอร์ที่แตกสลายจากสิ่งนี้


@ PéterTörökคุณพูดถูกสิ :)
Karlson

1
ใช่ แต่ขอให้สังเกตว่ามันไม่ได้พูดอะไรเกี่ยวกับตัวชี้จริง ๆ แล้วมีค่าตัวเลขเป็น 0 มันอาจไม่ได้ แต่บนแพลตฟอร์มส่วนใหญ่
Jan Hudec
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.