このコードは厳密なエイリアシングに違反していますか?
struct {int x;} a;
*(int*)&a = 3
より抽象的に言えば、プリミティブな読み取り/書き込み操作が正しい型である限り、異なる型間でキャストすることは合法ですか?
このコードは厳密なエイリアシングに違反していますか?
struct {int x;} a;
*(int*)&a = 3
より抽象的に言えば、プリミティブな読み取り/書き込み操作が正しい型である限り、異なる型間でキャストすることは合法ですか?
まず、C でキャストすることは合法です。 §6.7.2.1/13:
構造体オブジェクト内で、非ビット フィールド メンバーとビット フィールドが存在するユニットには、宣言された順序で増加するアドレスがあります。適切に変換された構造体オブジェクトへのポインターは、その最初のメンバー (または、そのメンバーがビットフィールドの場合は、それが存在するユニット) を指し、その逆も同様です。構造体オブジェクト内に名前のないパディングがある場合がありますが、先頭にはありません。
エイリアシング ルールは次のようになります (§6.5/7)。
オブジェクトは、次の型のいずれかを持つ左辺値式によってのみアクセスされる格納された値を持つものとします。
- オブジェクトの有効な型と互換性のある型、
- オブジェクトの有効な型と互換性のある修飾された型のバージョン、
- オブジェクトの有効な型に対応する符号付きまたは符号なしの型である型、
- オブジェクトの有効な型の修飾されたバージョンに対応する符号付きまたは符号なしの型である型、
- 前述のタイプのいずれかをメンバーに含む集約型または共用体型 (再帰的に、サブ集約または包含共用体のメンバーを含む)、または
- 文字タイプ。
ここでは、「オブジェクトの有効な型と互換性のある型」および「メンバーに前述の型のいずれかを含む集約型または共用体型」のポインターを介してアクセスするため、エイリアスも問題ありません。したがって、C では、構造体へのポインターを問題のメンバーの型にキャストすることによって、構造体の最初のメンバーにアクセスすることは完全に合法です。
ただし、C++ では、C++ オブジェクトの先頭に vtable やその他のものがあることがよくあります。ただし、特定のケースでは、構造は標準レイアウトであるため、これは明示的に許可されています (n3290 の§9.2/20、Luc Danton に感謝します! - C++03 には、POD オブジェクトに関して表現された同様のルールがあるようです)。 .