47

これは、 Rob Walkerの回答hereによって引き起こされた質問です。

次のようにクラス/構造体を宣言するとします。

struct
{ 
    char A;
    int B;
    char C;
    int D;
};

これらのメンバーがメモリ内で正確にその順序で宣言されると想定しても安全ですか、それともコンパイラに依存するものですか? 私が質問しているのは、コンパイラがそれらを使って何でもできるといつも思っていたからです。

これは私の次の質問につながります。上記の例でメモリ アラインメントの問題が発生する場合、コンパイラはそれを暗黙的に次のように変換できないのはなぜですか。

struct
{ 
    char A;
    char C;
    int B;
    int D;
};

(私は主に C++ について質問していますが、C の回答も聞きたいです)

関連トピック

4

6 に答える 6

80

C99 §6.7.2.1 条項 13 は次のように述べています。

構造体オブジェクト内では、ビットフィールド以外のメンバーとビットフィールドが存在するユニットのアドレスは、宣言された順序で増加します。

さらに、パディングとアドレスについてもう少し説明します。C89 に相当するセクションは §6.5.2.1 です。

C++ はもう少し複雑です。1998 年および 2003 年の標準には、§9.2 の 12 節 (C++11 の 15 節) があります。

access-specifier を介在させずに宣言された (非共用体) クラスの非静的データ メンバーは、後のメンバーがクラス オブジェクト内でより高いアドレスを持つように割り当てられます。アクセス指定子で区切られた非静的データ メンバの割り当て順序は規定されていません (11.1)。実装のアライメント要件により、隣接する 2 つのメンバーが互いの直後に割り当てられない場合があります。仮想関数 (10.3) および仮想基本クラス (10.1) を管理するためのスペースの要件も同様です。

于 2008-11-11T14:50:01.970 に答える
4

データ メンバーは、宣言された順序で配置されます。コンパイラは、好みのメモリ アラインメントを調整するためにパディングを自由に散在させることができます (そして、多くのコンパイラにはアラインメント指定オプションのボートロードがあることがわかります。これは、異なるプログラムによってコンパイルされたビットを混在させる場合に役立ちます)。

GCC が構造体を最適化しないのはなぜですか?も参照してください。.


この回答は、C++ ではやや時代遅れになっているようです。あなたは毎日何かを学びます。ありがとう、ネマニャ。

于 2008-11-11T14:46:16.970 に答える
3

基本的に、それは標準的なレイアウトのクラスにのみ当てはまります。厳密に言えば、標準レイアウトは C++0x のものですが、実際には既存のプラクティスを標準化しているだけです/

于 2008-11-11T14:47:09.370 に答える
3

C++ について話すことはできませんが、C では、構造体で宣言されたメモリ内の順序と同じであることが保証されています。

于 2008-11-11T14:46:14.910 に答える
2

アラインメントのためのパディングを除いて、C または C++ のコンパイラ (私が認識している) では、構造の最適化は許可されていません。C++ クラスについては、まったく別の獣である可能性があるため、話すことはできません。

プログラムが Windows のシステム/ライブラリ コードとインターフェイスしているが、GCC を使用したいと考えています。MS でコンパイルされたコードに送信する前に、GCC が同一のレイアウト最適化アルゴリズムを使用していることを確認して、すべての構造が正しくパックされるようにする必要があります。

于 2008-11-11T14:51:30.220 に答える
0

右側の関連トピックを参照しながら、この質問を見ました。これらの問題について考えるとき、これは興味深いコーナーケースかもしれないと思います (私が認識しているよりも一般的でない限り)。

言い換えると、C で次のような構造体があるとします。

struct foo{};

C++ のようにサブクラス化します (別のコンパイル ユニットを使用):

extern "C" foo;
struct bar: public foo{};

次に、 aibが言及する理由により、メモリアライメントは必ずしも同じではありません(同じベンダーのコンパイラ間でも)。

于 2008-11-11T15:10:45.670 に答える