พิจารณารหัส C ++ ต่อไปนี้:
void* a = &a;
เหตุใดคอมไพเลอร์จึงไม่บ่นเรื่องการใช้ตัวระบุที่ไม่ได้ประกาศ
นอกจากนี้คอมไพเลอร์พิจารณาว่าตัวแปรaเป็นอย่างไร เป็นตัวชี้ไปยังวัตถุที่ว่างเปล่าหรือเป็นตัวชี้ไปยังvoid*ตัวชี้?
พิจารณารหัส C ++ ต่อไปนี้:
void* a = &a;
เหตุใดคอมไพเลอร์จึงไม่บ่นเรื่องการใช้ตัวระบุที่ไม่ได้ประกาศ
นอกจากนี้คอมไพเลอร์พิจารณาว่าตัวแปรaเป็นอย่างไร เป็นตัวชี้ไปยังวัตถุที่ว่างเปล่าหรือเป็นตัวชี้ไปยังvoid*ตัวชี้?
คำตอบ:
ขอบเขตของการประกาศตัวแปรใน C ++ นั้นค่อนข้างน่าแปลกใจ:
void* a = &a;
^~~~~~~~~~~~~~~~~
a declared as `void*` from here on
ดังนั้น&aเป็นvoid**แต่เนื่องจากตัวชี้ประเภทใดโดยปริยายแปลงสภาพให้แก่void*...
a = &userfulObject?
void *a = a;จะเป็น UB หากประกาศในเครื่องมิฉะนั้นจะใช้ได้ดีในขอบเขตเนมสเปซ
เทียบเท่ากับ
void* a;
a = &a;
จึงaได้มีการประกาศ ดังนั้นaได้รับที่อยู่ของเขียนในa aดังนั้นจึงเป็นตัวชี้ไปยังตัวชี้โมฆะ (คุณยังไม่ได้กำหนดวัตถุใด ๆ )
aตัวเองเป็นวัตถุ (ไม่ใช่ทุกวัตถุที่มีประเภทที่ผู้ใช้กำหนดเองใน C ++)
ในvoid* a, aมีการประกาศเป็นตัวชี้ไม่ได้กับvoidประเภท แต่ที่ "ใด ๆ" ชนิด (กรณีพิเศษ) แน่นอนว่ามีการกำหนดที่อยู่ (ตำแหน่งในหน่วยความจำ) ให้กับaตัวแปรอื่น ๆ ที่ประกาศ
หลังจากนั้นนิพจน์&aจะถูกประเมินเพื่อเตรียมใช้งานตัวแปร (เช่นaกัน แต่ไม่เกี่ยวข้อง) ที่เพิ่งประกาศ ประเภทของ&aคือ "ตัวชี้เพื่อชี้ไปยังประเภทใด ๆ " ซึ่งเป็นกรณีพิเศษของ "ตัวชี้ไปยังประเภทใด ๆ " ซึ่งเข้ากันได้กับประเภทของa. Ergo ไม่มีข้อความคอมไพเลอร์
Corollary: อย่าใช้void*ถ้าคุณต้องการตรวจสอบประเภทที่แข็งแกร่ง สิ่งใดสามารถแปลงเป็นมันได้ ตรงกันข้ามในทิศทางย้อนกลับยกเว้นvoid*ตัวมันเอง (จะเป็นข้อยกเว้นที่ไม่จำเป็นที่ประเภทไม่เข้ากันกับตัวมันเอง)
นอกจากนี้ AFAIR นี้มาจาก C.