ここでの問題は、厳密なエイリアシングではなく、構造表現の要件です。
char
まず、 、signed char
、またはunsigned char
と他の型 (あなたの場合は) の間でエイリアスを作成しても安全です。これにより、型unsigned int
を使用して定義されている限り、独自のメモリ コピー ループを作成できます。これは、 char
C99 の次の言語 (§6.5):
6. 格納された値にアクセスするためのオブジェクトの有効な型は、オブジェクトの宣言された型です (存在する場合)。[脚注: 割り当てられたオブジェクトには型が宣言されていません] [...] memcpy または memmove を使用して型が宣言されていないオブジェクトに値がコピーされた場合、または文字型の配列としてコピーされた場合、変更されたオブジェクトの有効な型そのアクセスと、値を変更しない後続のアクセスの場合、値がコピーされるオブジェクトの有効な型です (存在する場合)。宣言された型を持たないオブジェクトへの他のすべてのアクセスでは、オブジェクトの有効な型は、単にアクセスに使用される左辺値の型です。
7. オブジェクトは、次のタイプのいずれかを持つ左辺値式によってのみアクセスされる保存された値を持つものとします。
- オブジェクトの有効な型と互換性のある型、
- [...]
- 文字タイプ。
同様の言語が C++0x ドラフト N3242 §3.11/10 にありますが、オブジェクトの「動的型」がいつ割り当てられるかは明確ではありません (動的型が何であるかについてのさらなる参照をいただければ幸いですPOD オブジェクトが適切な配置で char 配列としてコピーされた char 配列)。
そのため、エイリアシングはここでは問題になりません。ただし、標準を厳密に読むと、C++ の実装では の表現を自由に選択できることがわかりunsigned int
ます。
1 つのランダムな例として、unsigned int
s は 4 バイトで表され、8 つのパディング ビットが散在する 24 ビット整数である可能性があります。これらのパディング ビットのいずれかが特定の (一定の) パターンと一致しない場合、それはトラップ表現と見なされ、ポインターの逆参照はクラッシュを引き起こします。これは実装の可能性がありますか?おそらくそうではありません。しかし、歴史的には、パリティ ビットやその他の奇妙な機能を備えたシステムが存在したため、標準を厳密に読み取ることによってunsigned int
、ネットワークから に直接読み取ることはコーシャではありません。
現在、ビットのパディングの問題は、今日のほとんどのシステムでほとんどが理論的な問題ですが、注目に値します。PC ハードウェアに固執する場合は、特に心配する必要はありません (ただし、ntohl
s を忘れないでください - エンディアンは依然として問題です!)
もちろん、構造はそれをさらに悪化させます - アラインメント表現はプラットフォームに依存します。私は、すべてのタイプのアライメントが 1 である組み込みプラットフォームで作業しました。構造体にパディングが挿入されることはありません。これにより、複数のプラットフォームで同じ構造定義を使用すると、矛盾が生じる可能性があります。データ構造メンバーのバイト オフセットを手動で計算して直接参照するか、コンパイラ固有のアラインメント ディレクティブを使用してパディングを制御できます。
そのため、ネットワーク バッファーからネイティブの型または構造体に直接キャストする場合は注意が必要です。しかし、この場合、エイリアシング自体は問題になりません。