พิจารณาโครงสร้างต่อไปนี้:
struct s {
int a, b;
};
โดยทั่วไป1 โครงสร้างนี้จะมีขนาด 8 และการจัดตำแหน่ง 4
จะเกิดอะไรขึ้นถ้าเราสร้างstruct s
วัตถุสองชิ้น (แม่นยำยิ่งกว่านั้นเราเขียนลงในวัตถุสองหน่วยดังกล่าวที่จัดสรรแล้ว) โดยที่วัตถุที่สองซ้อนทับวัตถุแรก
char *storage = malloc(3 * sizeof(struct s));
struct s *o1 = (struct s *)storage; // offset 0
struct s *o2 = (struct s *)(storage + alignof(struct s)); // offset 4
// now, o2 points half way into o1
*o1 = (struct s){1, 2};
*o2 = (struct s){3, 4};
printf("o2.a=%d\n", o2->a);
printf("o2.b=%d\n", o2->b);
printf("o1.a=%d\n", o1->a);
printf("o1.b=%d\n", o1->b);
มีอะไรเกี่ยวกับโปรแกรมนี้ที่ไม่ได้กำหนดพฤติกรรมหรือไม่ ถ้าเป็นเช่นนั้นจะไม่ได้กำหนดที่ไหน? หากไม่ใช่ UB รับประกันว่าจะพิมพ์ดังต่อไปนี้เสมอ:
o2.a=3
o2.b=4
o1.a=1
o1.b=3
โดยเฉพาะอย่างยิ่งฉันต้องการทราบว่าเกิดอะไรขึ้นกับวัตถุที่ชี้ไปo1
เมื่อo2
เขียนทับกัน มันยังคงได้รับอนุญาตให้เข้าถึงส่วนที่ยังไม่ได้ล็อค ( o1->a
) หรือไม่? การเข้าถึงส่วนที่ถูกบดบังo1->b
นั้นเหมือนกับการเข้าถึงo2->a
หรือไม่?
อย่างไรชนิดที่มีประสิทธิภาพใช้ที่นี่? กฎมีความชัดเจนเพียงพอเมื่อคุณกำลังพูดถึงวัตถุและตัวชี้ที่ไม่ทับซ้อนกันซึ่งชี้ไปที่ตำแหน่งเดียวกันกับที่เก็บครั้งสุดท้าย แต่เมื่อคุณเริ่มพูดถึงชนิดของส่วนของวัตถุที่มีประสิทธิภาพหรือวัตถุที่ทับซ้อนกัน
จะมีอะไรเปลี่ยนแปลงไหมถ้าการเขียนครั้งที่สองเป็นประเภทที่แตกต่างกัน ถ้าสมาชิกพูดint
และshort
มากกว่าสองคนint
?
นี่คือรูปสลักถ้าคุณต้องการเล่นกับมันที่นั่น
1คำตอบนี้นำไปใช้กับแพลตฟอร์มที่ไม่มีกรณีเช่น: บางคนอาจมีขนาด 4 และการจัดตำแหน่ง 2 บนแพลตฟอร์มที่ขนาดและการจัดตำแหน่งเหมือนกันคำถามนี้จะไม่นำมาใช้ตั้งแต่จัดเรียงวัตถุที่ทับซ้อนกัน เป็นไปไม่ได้ แต่ฉันไม่แน่ใจว่ามีแพลตฟอร์มใด ๆ เช่นนั้น