それは標準によって定義されているので、公式であろうとなかろうと、誰が何を言おうと、それは未定義の振る舞いではありません。p->s
、左辺値として使用される場合を除いて、と同じポインタに評価されます(char *)p + offsetof(struct T, s)
。特に、これはchar
mallocされたオブジェクト内の有効なポインターであり、その直後に100個(またはそれ以上、配置の考慮事項によって異なります)の連続するアドレスがありchar
、割り当てられたオブジェクト内のオブジェクトとしても有効です。->
によって返されるポインタにオフセットを明示的に追加する代わりにmalloc
、にキャストすることによってポインタが派生したという事実char *
は関係ありません。
技術的にp->s[0]
は、構造体内の配列の単一要素でありchar
、次のいくつかの要素(たとえばp->s[1]
、からp->s[3]
)は、構造体内のバイトをパディングする可能性があります。これは、構造体全体への割り当てを実行すると破損する可能性がありますが、単に個別にアクセスする場合は破損しない可能性がありますメンバー、および残りの要素は、割り当てられたオブジェクト内の追加のスペースであり、配置要件に準拠している限り(またchar
、配置要件がない限り)、自由に使用できます。
構造体のパディングバイトと重複する可能性が何らかの形で鼻の悪魔を引き起こす可能性があることを心配している場合は、構造体の最後にパディングがないことを保証する値で1
inを置き換えることでこれを回避できます。[1]
これを行うための単純ですが無駄な方法は、最後に配列がないことを除いて同一のメンバーで構造体を作成しs[sizeof struct that_other_struct];
、配列に使用することです。次に、は、の構造体の配列の要素として、およびの構造体の終わりに続くアドレスのcharオブジェクトとしてp->s[i]
明確に定義されます。i<sizeof struct that_other_struct
i>=sizeof struct that_other_struct
編集:実際、適切なサイズを取得するための上記のトリックでは、配列自体が他の要素のパディングの途中ではなく最大の配置で始まるように、配列の前にすべての単純な型を含む共用体を配置する必要がある場合もあります。繰り返しになりますが、私はこれが必要であるとは思いませんが、私はそこにいる言語弁護士の中で最も妄想的な人のためにそれを提供しています。
編集2:標準の別の部分があるため、パディングバイトとの重複は間違いなく問題ではありません。Cでは、2つの構造体がそれらの要素の初期サブシーケンスで一致する場合、共通の初期要素にいずれかのタイプへのポインターを介してアクセスできる必要があります。結果として、より大きな最終配列と同一struct T
であるがより大きな最終配列を持つ構造体が宣言された場合、要素はの要素s[0]
と一致する必要があり、これらの追加要素の存在は、より大きな構造体の共通要素にアクセスすることによって影響を受けたり影響を受けたりすることはありません。へのポインタを使用します。s[0]
struct T
struct T