3

重複の可能性:
構造体の sizeof が各メンバーの sizeof の合計と等しくないのはなぜですか?

次のクラスが与えられ、他のデータ メンバーはありません。

typedef uint32_t id_t;
typedef int64_t loc_t;

class foo:
{
public:
    enum bar : uint8_t
    {
        BAR1,
        BAR2,
        BAR3
    };
private:
    id_t id;
    loc_t  start;
    loc_t  stop;
    bar std;
};

誰でも理由を説明できますか:

sizeof( id_t ) は 4 を返します...
sizeof( loc_t ) は 8 を返します...
sizeof( bar ) は 1 を返します...

4+(2*8)+1 = 21

まだ:

sizeof( foo ) は 32 を返しますか?

bar 列挙型の uint8_t 要件を削除しても、sizeof( bar ) は 4 (int) を返すだけで成功しますが、sizeof( foo ) は 24 が適切にバイト アラインされる場合でも 32 を返します。

編集:理由は十分に答えられています。それぞれがテーブルにさまざまな詳細をもたらしたので、コメントしてくれたすべての人に感謝します.

私が必要とする修正は、 sizeof() を使用してファイルの場所のオフセットを作成できるようにすることです。そのため、バイナリ形式でファイルに foo を書き込むと、後でその場所が与えられた場合に、その直後の場所を見つけることができます。エレガントな解決策が見つかったら、ここで更新します。

4

3 に答える 3

2

これは、メモリの配置が原因です。プロセッサはバスの幅に応じてデータをフェッチします。32 ビット OS はデータを 4 バイト境界に整列し、64 ビット OS は 8 バイト境界に整列します。Non-Aligned メモリは 2 回のメモリ読み取りを必要とし、パフォーマンスの低下につながります。

ここでメモリアライメントのすべてを読んでください:

  1. http://www.devx.com/tips/Tip/13265
  2. http://msdn.microsoft.com/en-us/library/83ythb65.aspx
于 2012-11-07T00:37:24.183 に答える
1

これはパディングによるものです。コンパイラは、より効率的なアクセスのために、構造体内の変数が適切に配置されるように、構造体に「スペース」を残す場合があります。

デフォルトの構造体メンバーのアラインメントをオーバーライドできます (少なくとも MSVC では、#pragma pack.

于 2012-11-07T00:39:46.300 に答える
1

型はint64_ts のためにおそらく 8 バイト アラインされているので、

sizeof(id_t) + 4 bytes padding + 2*sizeof(loc_t) + `sizeof(uint8_t)` + padding up to the next multiple of 8 =
4 + 4 bytes of padding + 16 + 1 + (padding up to the next multiple of 8) =
25 + padding to multiple of 8 =
32

一部のコンパイラにはパディングに関する警告があります (clang には -Wpadded があります)。

warning: padding class 'foo' with 4 bytes to align 'start' [-Wpadded]
    loc_t  start;
           ^
warning: padding size of 'foo' with 7 bytes to alignment boundary [-Wpadded]
class foo
      ^

次のようなコンパイラ拡張機能を使用して、これを制御することもできます。#pragma pack(1)

#pragma pack(1)
class foo:
{
public:

もちろん、これにはパフォーマンス上のペナルティがありますが、この方法で sizeof(foo)は、このシステムでは 21 と表示されます。

于 2012-11-07T00:42:05.093 に答える