1. ホーム
  2. c

[解決済み] C言語による構造体メモリレイアウト

2023-01-26 02:52:20

質問

私はC#のバックグラウンドを持っています。Cのような低レベルの言語にはとても初心者です。

C#では struct のメモリは、デフォルトでコンパイラによってレイアウトされます。コンパイラはデータ フィールドを並べ替えたり、フィールド間に追加のビットを暗黙のうちに埋め込むことができます。そのため、正確なレイアウトのために、この動作を上書きする特別な属性を指定する必要がありました。

のメモリレイアウトを並べ替えたり整列させたりすることはありません。 struct のメモリレイアウトを変更したり整列させたりしません。しかし、ちょっとした例外があるそうで、それを見つけるのは非常に難しいそうです。

C言語のメモリレイアウトの動作はどうなっているのでしょうか?何が再注文/整列されるべきで、何がされないのでしょうか?

どのように解決するのですか?

C言語では、コンパイラはすべてのプリミティブ型に対してある種のアライメントを指示することが許されています。一般的に、アラインメントは型のサイズです。しかし、それは完全に実装に依存します。

パディングバイトが導入され、すべてのオブジェクトが適切に整列されます。並べ替えは許されません。

おそらく、最新のコンパイラはすべて #pragma pack を実装しており、パディングの制御を可能にし、ABIに準拠することをプログラマに委ねています。(これは厳密には非標準ですが)。

C99 §6.7.2.1 より。

12 構造体またはユニオン・オブジェクトの各非ビットフィールド・メンバーは 構造体またはユニオンオブジェクトの非ビットフィールドの各メンバーは、実装で定義された方法で 実装で定義された方法で 配置されます。

13 構造体オブジェクトの中で 構造体オブジェクトの中で、ビットフィールドでない ビットフィールドが存在するユニットと ビットフィールドが存在するユニットのアドレスは 宣言された順番に増加するアドレスを持っています。 が宣言された順に増加するアドレスを持ちます。構造体オブジェクトへのポインタを適切に変換すると オブジェクトへのポインタは、適切に変換された後、次の場所を指します。 その初期メンバ(そのメンバがビットフィールドの場合 ビットフィールドであれば,その中のユニットを指します。 を指し、その逆も同様です。 構造体オブジェクトの中に無名のパディングがある場合があります。 構造体オブジェクトの中に無名のパディングがあってもよいのですが、その先頭にはありません。 構造体オブジェクトの先頭にはありません。