Hãy xem xét các cấu trúc sau:
struct s {
int a, b;
};
Thông thường 1 , cấu trúc này sẽ có kích thước 8 và căn 4.
Điều gì sẽ xảy ra nếu chúng ta tạo hai struct s
đối tượng (chính xác hơn là chúng ta ghi vào lưu trữ được phân bổ hai đối tượng như vậy), với đối tượng thứ hai chồng lên đối tượng thứ nhất?
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);
Có bất cứ điều gì về chương trình này không xác định hành vi? Nếu vậy, nó trở nên không xác định ở đâu? Nếu không phải là UB, có đảm bảo luôn in như sau:
o2.a=3
o2.b=4
o1.a=1
o1.b=3
Cụ thể, tôi muốn biết những gì xảy ra với đối tượng được chỉ vào o1
khi nào o2
, nó chồng lên nó, được viết. Nó vẫn được phép truy cập vào phần không bị che khuất ( o1->a
)? Là truy cập vào phần bị ghi đè o1->b
đơn giản giống như truy cập o2->a
?
Làm thế nào để loại hiệu quả áp dụng ở đây? Các quy tắc đủ rõ ràng khi bạn nói về các đối tượng và con trỏ không chồng lấp chỉ đến cùng một vị trí với cửa hàng cuối cùng, nhưng khi bạn bắt đầu nói về loại phần hiệu quả của các đối tượng hoặc các đối tượng chồng chéo thì nó không rõ ràng.
Sẽ có gì thay đổi nếu lần viết thứ hai thuộc loại khác? Nếu các thành viên đã nói int
và short
hơn hai int
s?
Đây là một cú hích nếu bạn muốn chơi với nó ở đó.
1 Câu trả lời này áp dụng cho các nền tảng không phải là trường hợp tương tự: ví dụ: một số có thể có kích thước 4 và căn chỉnh 2. Trên nền tảng có kích thước và căn chỉnh giống nhau, câu hỏi này sẽ không áp dụng vì các đối tượng chồng chéo, chồng chéo sẽ là không thể, nhưng tôi không chắc có nền tảng nào như vậy không.