これを読んで、構造体に互換性のあるメンバーがある場合、つまり次の構造体が与えられている場合、(標準に違反することなく) 構造体にエイリアスを設定できることがわかりました。
typedef struct {
uint32_t a;
uint32_t b;
} Frizzly;
以下はエイリアシングの規則に違反します:
uint32_t foo(uint16_t *i) {
Frizzly *f = (Frizzly *)i;
return f->a;
}
ただし、次の場合はそうではありません。
uint32_t foo(uint32_t *i) {
Frizzly *f = (Frizzly *)i;
return f->b;
}
問題の「集約型」には、キャストするポインターと互換性のある型が含まれているためです。つまり、型へのポインターは、エイリアス規則を破ることなくuint32_t
、型のメンバー (またはメンバー) を含む構造体にキャストできます。uint32_t
まず、これを正しく理解できましたか?
次に、構造体内の (他の) 変数の順序と型は重要ですか? が次のようFrizzly
に定義されているとします。
typedef struct {
uint16_t b[2];
uint32_t a;
}
2 番目の例のキャストの後、互換性のない ( ) 型b
のメモリによってサポートされるようになりました。uint32_t
キャストはまだ有効ですか (または、キャストされたポインターを介して値にアクセスします)? のいずれかの要素を変更すると、厳密なエイリアシングが無効になっているかのように、a
の最初の要素の値が変更されますか?i
また、上記が有効な場合、次のような構造体がある場合はどうなりますか:
typedef struct {
void *m;
uint16_t hooah[4];
} Bar;
次のキャストは、私が正しければ、エイリアシング ルールに違反します。
void test(char *boo, size_t dee) {
Bar *bar = (Bar *)(boo + dee);
do_other_stuff(bar);
}
単一のunsigned char
メンバーを構造体に追加するだけで、キャストを有効にすることはできますか? 言い換えると、互換性のない型のポインターをキャストすると、通常、エイリアシング規則が破られますが、型のメンバーを含む構造体X
へのポインターからポインターへX
のキャストは例外であるため、X へのポインターから集計 Y へのキャストはすべて可能です。タイプXの(おそらくダミーの)メンバーをYに追加するだけで有効になりますか?
(上記のコード スニペットをコンパイラで実際にテストしたわけではありません。)
編集:
私の言い回しと例はかなり貧弱かもしれないことを知っているので、質問を言い換えてみます: 私が正しく理解していれば、構造体へのポインターが型 'X' の要素の配列をエイリアスすることは合法です。構造体には「X」型のメンバーが含まれています。現在、構造体のメンバーを逆参照する場合、メンバーは型 'X' である必要がありますか。適切なタイプ?