8

この質問から、組合の調整は、その個々のメンバーの最大の調整以上であると信じ始めることができます。しかしlong long、gcc /g++の型に問題があります。完全な例はここにありますが、私の質問に関連する部分は次のとおりです。

union ull {
  long long m;
};

struct sll {
  long long m;
};


int main() {
#define pr(v) cout << #v ": " << (v) << endl
   pr(sizeof(long long));
   pr(__alignof__(long long));
   pr(sizeof(ull));
   pr(__alignof__(ull));
   pr(sizeof(sll));
   pr(__alignof__(sll));
};

これにより、次の出力が得られます。

sizeof(long long): 8
__alignof__(long long): 8
sizeof(ull): 8
__alignof__(ull): 4
sizeof(sll): 8
__alignof__(sll): 4

組合員の配置が、それを含む組合の配置よりも大きいのはなぜですか?

[アップデート]

キースの答えによると、alignofはここでは間違っています。しかし、私は以下をテストし、alignof が私たちに真実を教えてくれるようです。見る:

union ull {
  long long m;
};
long long a;
char b;
long long c;
char d;
ull e;
int main() {
#define pr(v) cout << #v ": " << (v) << endl
   pr(size_t((void*)&b));
   pr(size_t((void*)&c));
   pr(size_t((void*)&d));
   pr(size_t((void*)&e));
   pr(size_t((void*)&c) - size_t((void*)&b));
   pr(size_t((void*)&e) - size_t((void*)&d));
};

出力:

size_t((void*)&b): 134523840
size_t((void*)&c): 134523848
size_t((void*)&d): 134523856
size_t((void*)&e): 134523860
size_t((void*)&c) - size_t((void*)&b): 8
size_t((void*)&e) - size_t((void*)&d): 4

したがって、グローバルデータでは、のアラインメントlong longは8であり、ユニオンを含むアラインメントは4です。long longローカルスコープの場合、コンパイラはローカルデータを自由に再配置できるように見えるため、これをテストすることはできません。したがって、このトリックは機能しません。これについてコメントできますか?

[/アップデート]

4

1 に答える 1

7

__alignof__(これはgcc拡張です)は、型に必要な配置を必ずしも報告しません。

たとえば、x86プロセッサでは、どのタイプでも1バイトを超えるアライメントは必要ありません。オブジェクトがワードアラインされている場合、4バイトまたは8バイトのオブジェクトへのアクセスはより効率的である可能性がありますが、バイトアラインメントで十分です。

gccドキュメントの引用:

一部のマシンは実際に位置合わせを必要としません。奇数アドレスでも任意のデータ型を参照できます。これらのマシン __alignof__の場合、通常はターゲットABIによって義務付けられているように、GCCがデータ型に与える最小のアライメントを報告します。

しかし、それでも実際には質問に答えることはできません。その緩い定義があっても、を含む構造体または共用体よりも__alignof__厳密な配置を示す正当な理由は考えられません。long longlong long

タイプの配置を決定するためのよりポータブルな方法は次のとおりです。

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t)))

これにより、aとatで構成される構造体の型のメンバーのオフセットが生成されます。このマクロを使用して、このプログラム:chart

#include <iostream>
#include <cstddef>

union ull {
  long long m;
};

struct sll {
  long long m;
};

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t)))

int main() {
#define pr(v) std::cout << #v ": " << (v) << std::endl
   pr(sizeof(long long));
   pr(__alignof__(long long));
   pr(ALIGNOF(long long));
   pr(sizeof(ull));
   pr(__alignof__(ull));
   pr(ALIGNOF(ull));
   pr(sizeof(sll));
   pr(__alignof__(sll));
   pr(ALIGNOF(sll));
};

私のシステム(gcc-4.7、Ubuntu 12.04、x86)でこの出力を生成します:

sizeof(long long): 8
__alignof__(long long): 8
ALIGNOF(long long): 4
sizeof(ull): 8
__alignof__(ull): 4
ALIGNOF(ull): 4
sizeof(sll): 8
__alignof__(sll): 4
ALIGNOF(sll): 4

ALIGNOF()私のマクロによって示される結果は一貫しlong longています。4バイトのアラインメントがあり、を含む構造体または共用体にlong longは4バイトのアラインメントがあります。

これは、gccのの実装におけるバグまたは少なくとも矛盾であると思われ__alignof__ます。しかし、定義があいまいなため、それが本当にバグであるかどうかを確認するのは困難です。報告されていないようです

アップデート :

銃を飛び越えているかもしれませんが、バグレポートを提出しました。

「INVALID」として閉じられたこの以前のバグレポートも同様ですが、構造自体の配置については言及していません。

アップデート2:

私のバグレポートは、以前のレポートの複製として閉じられました。説明をお願いします。

于 2012-08-06T09:10:03.040 に答える