void * a = & a legal ได้อย่างไร?


88

พิจารณารหัส C ++ ต่อไปนี้:

void* a = &a;

เหตุใดคอมไพเลอร์จึงไม่บ่นเรื่องการใช้ตัวระบุที่ไม่ได้ประกาศ

นอกจากนี้คอมไพเลอร์พิจารณาว่าตัวแปรaเป็นอย่างไร เป็นตัวชี้ไปยังวัตถุที่ว่างเปล่าหรือเป็นตัวชี้ไปยังvoid*ตัวชี้?




15
ควรพูดถึงเหตุผลที่คุณต้องการทำสิ่งนี้ - เพื่อให้ตัวชี้ไปที่ด้านบนสุดของสแต็ก (ซึ่งคุณสามารถเล่นซอกับสิ่งต่างๆได้ทุกประเภท)
OrangeDog

คำตอบ:


95

ขอบเขตของการประกาศตัวแปรใน C ++ นั้นค่อนข้างน่าแปลกใจ:

void* a =               &a;
         ^~~~~~~~~~~~~~~~~
          a declared as `void*` from here on

ดังนั้น&aเป็นvoid**แต่เนื่องจากตัวชี้ประเภทใดโดยปริยายแปลงสภาพให้แก่void*...


ฉันจะกำหนดวัตถุที่มีประโยชน์ให้กับสิ่งนี้ได้อย่างไร
user2681063

22
@ user2681063 a = &userfulObject?
Nikos C.

4
@MarkGarcia: โปรดทราบว่าvoid *a = a;จะเป็น UB หากประกาศในเครื่องมิฉะนั้นจะใช้ได้ดีในขอบเขตเนมสเปซ
Nawaz

1
@TheodorosChatzigiannakis: ฉันจะเชื่อว่ามันใช่
Matthieu M.

1
การอ้างอิงข้อมูลจำเพาะจะดีมากที่นี่
Benjamin Gruenbaum

30

เทียบเท่ากับ

void* a;
a = &a;

จึงaได้มีการประกาศ ดังนั้นaได้รับที่อยู่ของเขียนในa aดังนั้นจึงเป็นตัวชี้ไปยังตัวชี้โมฆะ (คุณยังไม่ได้กำหนดวัตถุใด ๆ )


9
ในทางเทคนิคคุณได้กำหนดวัตถุหนึ่งชิ้น aตัวเองเป็นวัตถุ (ไม่ใช่ทุกวัตถุที่มีประเภทที่ผู้ใช้กำหนดเองใน C ++)
MSalters

1
@MSalters คุณพูดถึง 'วัตถุ' นี้คืออะไร? : D
Gusdor

3
@Gusdor เราสามารถสันนิษฐานได้ว่าสิ่งที่อยู่นอกเหนือจากความว่างเปล่าของขอบฟ้าเหตุการณ์
Cole Johnson

พวกเขาเรียกต่างกัน แต่ "ผล" เหมือนกันในกรณีนี้
Stasik

พวกเขาจะไม่เทียบเท่าในทั่วไป แต่ในนี้สถานการณ์ที่พวกเขามี
Lightness Races ใน Orbit

7

ในvoid* a, aมีการประกาศเป็นตัวชี้ไม่ได้กับvoidประเภท แต่ที่ "ใด ๆ" ชนิด (กรณีพิเศษ) แน่นอนว่ามีการกำหนดที่อยู่ (ตำแหน่งในหน่วยความจำ) ให้กับaตัวแปรอื่น ๆ ที่ประกาศ

หลังจากนั้นนิพจน์&aจะถูกประเมินเพื่อเตรียมใช้งานตัวแปร (เช่นaกัน แต่ไม่เกี่ยวข้อง) ที่เพิ่งประกาศ ประเภทของ&aคือ "ตัวชี้เพื่อชี้ไปยังประเภทใด ๆ " ซึ่งเป็นกรณีพิเศษของ "ตัวชี้ไปยังประเภทใด ๆ " ซึ่งเข้ากันได้กับประเภทของa. Ergo ไม่มีข้อความคอมไพเลอร์

Corollary: อย่าใช้void*ถ้าคุณต้องการตรวจสอบประเภทที่แข็งแกร่ง สิ่งใดสามารถแปลงเป็นมันได้ ตรงกันข้ามในทิศทางย้อนกลับยกเว้นvoid*ตัวมันเอง (จะเป็นข้อยกเว้นที่ไม่จำเป็นที่ประเภทไม่เข้ากันกับตัวมันเอง)

นอกจากนี้ AFAIR นี้มาจาก C.

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