สำหรับ VC ต่อไปนี้เป็นการทดสอบเกี่ยวกับการประกาศล่วงหน้าและการระบุประเภทพื้นฐาน:
- รหัสต่อไปนี้จะรวบรวมตกลง
typedef int myint;
Enum T;
โมฆะ foo (T * tp)
{
* tp = (T) 0x12345678;
}
enum T: ตัวละคร
{
};
แต่ได้รับคำเตือนสำหรับ / W4 (/ W3 ไม่ได้รับคำเตือนนี้)
คำเตือน C4480: ส่วนขยายที่ไม่เป็นมาตรฐานที่ใช้: การระบุประเภทพื้นฐานสำหรับ enum 'T'
VC (Microsoft (R) 32-bit C / C ++ การปรับแต่งคอมไพเลอร์เวอร์ชั่น 15.00.30729.01 สำหรับ 80x86) ดูบั๊กในกรณีข้างต้น:
- เมื่อเห็น enum T; VC ถือว่า enum type T ใช้ค่าเริ่มต้น 4 ไบต์ int เป็นชนิดข้อมูลอ้างอิงดังนั้นรหัสแอสเซมบลีที่สร้างขึ้นคือ:
? foo @@ YAXPAW4T @@@ Z PROC; foo
; ไฟล์ e: \ work \ c_cpp \ cpp_snippet.cpp
; บรรทัดที่ 13
ผลักดัน ebp
mov ebp, esp
; บรรทัดที่ 14
mov eax, DWORD PTR _tp $ [ebp]
mov DWORD PTR [eax], 305419896; 12345678H
; บรรทัดที่ 15
ป๊อปอัพ
เกษียณ 0
? foo @@ YAXPAW4T @@@ Z ENDP; foo
รหัสการชุมนุมด้านบนถูกดึงมาจาก /Fest.asm โดยตรงไม่ใช่การเดาส่วนตัวของฉัน คุณเห็น mov DWORD PTR [eax], 305419896; เส้น 12345678H?
ข้อมูลโค้ดต่อไปนี้พิสูจน์ว่า:
int หลัก (int argc, ถ่าน * argv)
{
ยูเนี่ยน {
ถ่าน ca [4];
T t;
} ก;
a.ca [0] = a.ca [1] = a. [ca [2] = a.ca [3] = 1;
foo (& a.t);
printf ("% # x,% # x,% # x,% # x \ n", a.ca [0], a.ca [1], a.ca [2], a.ca [3]) ;
กลับ 0
}
ผลลัพธ์คือ: 0x78, 0x56, 0x34, 0x12
- หลังจากลบการประกาศล่วงหน้าของ enum T และย้ายคำจำกัดความของฟังก์ชั่น foo หลังจากคำจำกัดความของ enum T: ผลลัพธ์คือ OK:
คำสั่งสำคัญข้างต้นกลายเป็น:
mov BYTE PTR [eax], 120; 00000078H
ผลลัพธ์สุดท้ายคือ: 0x78, 0x1, 0x1, 0x1
หมายเหตุค่าจะไม่ถูกเขียนทับ
ดังนั้นการใช้การประกาศล่วงหน้าของ enum ใน VC จึงถือว่าเป็นอันตราย
BTW จะไม่แปลกใจไวยากรณ์สำหรับการประกาศประเภทพื้นฐานเป็นเช่นเดียวกับใน C # ในบทสนทนาฉันพบว่ามันคุ้มค่าที่จะบันทึก 3 ไบต์โดยการระบุประเภทพื้นฐานเป็นอักขระเมื่อพูดคุยกับระบบฝังตัวซึ่งเป็นหน่วยความจำ จำกัด