Đó không phải là hành vi không xác định , bất kể bất kỳ ai, quan chức hay người khác , nói gì, bởi vì nó được định nghĩa bởi tiêu chuẩn. p->s
, ngoại trừ khi được sử dụng làm giá trị, đánh giá một con trỏ giống hệt với (char *)p + offsetof(struct T, s)
. Đặc biệt, đây là một char
con trỏ hợp lệ bên trong đối tượng malloc'd và có 100 (hoặc nhiều hơn, phụ thuộc vào việc cân nhắc căn chỉnh) địa chỉ kế tiếp ngay sau nó, cũng có giá trị như char
các đối tượng bên trong đối tượng được cấp phát. Thực tế là con trỏ được tạo ra bằng cách sử dụng ->
thay vì thêm rõ ràng phần bù vào con trỏ được trả về malloc
, ép kiểu char *
, là không liên quan.
Về mặt kỹ thuật, p->s[0]
là một phần tử duy nhất của char
mảng bên trong cấu trúc, một vài phần tử tiếp theo (ví dụ: p->s[1]
thông qua p->s[3]
) có thể là các byte đệm bên trong cấu trúc, có thể bị hỏng nếu bạn thực hiện gán cho toàn bộ cấu trúc nhưng không phải nếu bạn chỉ truy cập riêng lẻ các thành viên và phần còn lại là không gian bổ sung trong đối tượng được cấp phát mà bạn có thể tự do sử dụng theo cách bạn muốn, miễn là bạn tuân theo các yêu cầu về căn chỉnh (và char
không có yêu cầu về căn chỉnh).
Nếu bạn lo lắng rằng khả năng chồng chéo với các byte đệm trong cấu trúc bằng cách nào đó có thể gọi ra quỷ mũi, bạn có thể tránh điều này bằng cách thay thế 1
in [1]
bằng một giá trị đảm bảo rằng không có phần đệm ở cuối cấu trúc. Một cách đơn giản nhưng lãng phí để làm điều này là tạo một cấu trúc với các thành viên giống hệt nhau ngoại trừ không có mảng nào ở cuối và sử dụng s[sizeof struct that_other_struct];
cho mảng. Sau đó, p->s[i]
được xác định rõ ràng là một phần tử của mảng trong struct for i<sizeof struct that_other_struct
và như một đối tượng char tại một địa chỉ theo sau phần cuối của struct for i>=sizeof struct that_other_struct
.
Chỉnh sửa: Trên thực tế, trong thủ thuật trên để có được kích thước phù hợp, bạn cũng có thể cần đặt một liên hợp chứa mọi kiểu đơn giản trước mảng, để đảm bảo rằng bản thân mảng bắt đầu với căn chỉnh tối đa thay vì ở giữa phần đệm của một số phần tử khác . Một lần nữa, tôi không tin rằng bất kỳ điều nào trong số này là cần thiết, nhưng tôi đang cung cấp nó cho những luật sư ngôn ngữ hoang tưởng nhất ngoài kia.
Chỉnh sửa 2: Sự chồng chéo với các byte đệm chắc chắn không phải là vấn đề, do một phần khác của tiêu chuẩn. C yêu cầu rằng nếu hai cấu trúc đồng ý trong một dãy con ban đầu của các phần tử của chúng, các phần tử ban đầu chung có thể được truy cập thông qua một con trỏ tới một trong hai kiểu. Do đó, nếu một cấu trúc giống hệt struct T
nhưng có mảng cuối cùng lớn hơn được khai báo, thì phần tử s[0]
sẽ phải trùng với phần tử s[0]
trong struct T
và sự hiện diện của các phần tử bổ sung này không thể ảnh hưởng hoặc bị ảnh hưởng khi truy cập các phần tử chung của cấu trúc lớn hơn bằng cách sử dụng một con trỏ tới struct T
.