これは主観的な質問です。「なぜスペックはこれを言っているのですか?」しかし、私はそれに私のショットを与えます。
関数内の変数は通常、他の期間(静的期間、スレッド期間、および割り当てられた期間)のいずれかとは対照的に、「自動」ストレージを備えています。
構造体では、オブジェクトのメモリレイアウトを明示的に定義しています。ただし、関数では、コンパイラーは不特定の方法で変数にストレージを自動的に割り当てます。x
ここに質問があります:スタック上で何バイトを占めますか?
// sizeof(unsigned) == 4
unsigned x;
4バイトを占めるか、8、12、または0を占めるか、同時に3つの異なるレジスター、またはスタックとレジスターに配置されるか、スタック上で4つの場所を取得する可能性があります。 。
重要なのは、コンパイラがあなたに代わって割り当てを行っているということです。スタックのレイアウトを行っていないため、ビット幅を指定しないでください。
拡張された議論:ビットフィールドは実際には少し特別です。仕様では、隣接するビットフィールドが同じストレージユニットにパックされると規定されています。ビットフィールドは実際にはオブジェクトではありません。
sizeof()
ビットフィールドはできません。
malloc()
ビットフィールドはできません。
&addressof
ビットフィールドはできません。
これらはすべて、Cのオブジェクトで実行できますが、ビットフィールドでは実行できません。ビットフィールドは、構造物のためだけに作られた特別なものであり、他のどこにもありません。
についてint24_t
(更新):一部のアーキテクチャでは機能しますが、他のアーキテクチャでは機能しません。少しでも持ち運びできません。
typedef struct {
int x : 24 __attribute__((packed));
} int24_t;
Linux ELF / x64、OS X / x86、OS X / x64 、sizeof(int24_t) == 3
。しかし、OS X / PowerPCでは、sizeof(int24_t) == 4
。
GCCがロード用に生成するコードint24_t
は、基本的にこれと同等であることに注意してください。
int result = (((char *) ptr)[0] << 16) |
(((unsigned char *) ptr)[1] << 8) |
((unsigned char *)ptr)[2];
単一の値をロードするための、x64での9つの命令です。