누구든지 공식적으로 말하든 그렇지 않든 간에 표준에 의해 정의 되었기 때문에 정의되지 않은 행동이 아닙니다 . p->s
, lvalue로 사용되는 경우를 제외하고는와 동일한 포인터로 평가됩니다 (char *)p + offsetof(struct T, s)
. 특히 이것은 char
malloc 객체 내부의 유효한 포인터이며 char
할당 된 객체 내부의 객체 로도 유효한 100 개 (또는 그 이상, 정렬 고려 사항에 따라 다름) 연속 주소가 바로 뒤에 있습니다 . 에서 ->
반환 된 포인터에 오프셋을 명시 적으로 추가하는 대신를 사용하여 포인터가 파생되었다는 사실은 malloc
캐스트 char *
와 관련이 없습니다.
기술적으로 p->s[0]
는 char
struct 내부 배열 의 단일 요소이며 다음 몇 개의 요소 (예 : p->s[1]
~ p->s[3]
)는 struct 내부의 패딩 바이트 일 가능성이 높습니다. 이는 struct 전체에 할당을 수행하면 손상 될 수 있지만 개별적으로 액세스하는 경우에는 그렇지 않습니다. 멤버 및 나머지 요소는 할당 된 개체의 추가 공간이며 정렬 요구 사항을 준수하고 정렬 요구 사항 char
이없는 한 원하는대로 자유롭게 사용할 수 있습니다 .
구조체의 패딩 바이트와 겹칠 가능성이 어떻게 든 비강 악마를 호출 할 수 있다고 걱정되면 1
in [1]
을 구조체 끝에 패딩이없는 값 으로 대체하여이를 피할 수 있습니다. 간단하지만 낭비적인 방법은 끝에 배열이없는 것을 제외하고는 동일한 멤버로 구조체를 만들고 배열에 사용 s[sizeof struct that_other_struct];
하는 것입니다. 그런 다음 p->s[i]
for 구조체의 배열 요소로 명확하게 정의되고 for 구조체 i<sizeof struct that_other_struct
의 끝 뒤에 오는 주소의 char 객체로 정의됩니다 i>=sizeof struct that_other_struct
.
편집 : 실제로, 올바른 크기를 얻기위한 위의 트릭에서, 배열 자체가 다른 요소의 패딩 중간이 아닌 최대 정렬로 시작되도록 배열 앞에 모든 단순 유형을 포함하는 공용체를 넣어야 할 수도 있습니다. . 다시 말하지만, 나는 이것이 필요하다고 생각하지 않지만, 거기에있는 가장 편집증적인 언어 변호사들을 위해 그것을 제공하고 있습니다.
편집 2 : 패딩 바이트와의 겹침은 표준의 다른 부분으로 인해 문제가되지 않습니다. C에서는 두 구조체가 요소의 초기 하위 시퀀스에서 일치하는 경우 두 유형에 대한 포인터를 통해 공통 초기 요소에 액세스 할 수 있어야합니다. 동일한 구조체 경우 결과적으로, struct T
그러나 더 큰 최종 배열이 선언 된, 요소가 s[0]
요소와 일치해야합니다 s[0]
에서 struct T
, 이러한 추가 요소의 존재에 영향을 줄 수 없거나 더 큰 구조체의 공통 요소에 액세스하여 영향을받을 수 에 대한 포인터 사용 struct T
.