2010-06-22 36 views
3

“字段是否可能与字段限定重叠是实现定义的。字段不需要命名;未命名的字段(仅限冒号和宽度)用于填充。特殊宽度0可用于强制在下一个字边界对齐。“不明白C标准中的位字段描述

我无法得到这些行。你能解释一下吗?

+0

你能否提供一些关于这些行从哪里来的内容? – Salgar 2010-06-22 13:00:07

+0

可能是C语言规范。 – samoz 2010-06-22 13:04:57

回答

0

首先它主要与记忆'对齐'有关。编译器通常在字边界上对齐变量或字段,在32位平台上一个字是32位。这意味着两个布尔将成为不同字中的第一个字节,而不是两个连续的字节。

位字段可以强制内存中的布局:如果某个特定字段的值介于0-7之间,则只能使用3位。

一个字段可以是未命名的。如果你不打算使用它,你不需要命名字段。这可能被用来强制一个特定的布局。

如果您使用:0,它会自动对齐下一个单词边界。

通常,除非以某种方式调整性能,否则不需要此行为。

1

基本上,如果地址是“字对齐”,处理器可以更快地执行操作。一个字通常是32位,或者4个字节。

典型的处理器是“字”对齐的,这意味着它们可以在一次操作中检索整个“字”。当值跨越多个值时,处理器必须执行多个操作才能获得相同的数据。有时候,例如,如果您使用的是“双字”,但如果您有一个单词跨越单词边界,则CPU必须执行2次操作才能检索单个数据单词,这是不可避免的。

字对齐值的示例是0x10000004,0x10000008。由于一个字是4个字节,所以地址必须可以被4整除。非字对齐的值是0x10000003。

对于程序员来说,所有的操作都可以按预期工作,但是在底层,CPU必须执行1次内存操作才能读取或写入0x10000004,而它必须执行2次内存操作才能读取或写入0x10000003,因为它跨越一个字的边界。

参考你原来的问题,这基本上是说,根据你使用的编译器,编译器可能会或可能不会对齐字段。这是尺寸与速度的一个例子,因为如果你没有字对齐,你可以打包更多的数据,但是如上所示,它会变慢。

5

“字段是否可能重叠字界限是实现定义的。

考虑的记忆,这里所说的尺寸是说32位的两句话:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] ... [2] [1] [0] 

如果我们有一个结构:

struct X 
{ 
    int a : 30; 
    int b : 4; 
}; 

然后,编译器可能选择将字段B所以部分是在每个单词中,或者它可能会留下间隙以便所有的b都落入第二个单词中:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] [28] ... [2] [1] [0] 
a--------------------a b-----------------b 
OR 
a--------------------a GAP b-----------------b 

为什么会留下GAP?因为那么当它想要读或写b时,它只需要处理内存中的一个字 - 这通常更快,更简单,需要更少的CPU指令。

字段不需要命名;未命名的字段(仅限冒号和宽度)用于填充。

如果我们改变了我们的前面结构,我们可以明确要求差距:

struct X 
{ 
    int a : 30; 
    int : 2; // unnamed field 
    int b : 4; 
}; 

这话说“离开A和B之间的2位 - 他们并不需要一个标识符(名字)因为我永远不会问他们有什么,或者需要问他们的价值是否会改变。“但是,你不必为了30 + 2 == 32(我们的单词大小)而做到这一点......你可以随心所欲地寻找任何你喜欢的差距。如果你正在处理来自某个硬件设备的值,并且你知道某些位是否是其他位,或者你不需要使用其中的某些位,这可能会很有用 - 您可以将它们保留为未命名你的不感兴趣,同时仍然让编译器将所需偏移量中的命名位字段空间放入与硬件使用对应的必要字中。

特殊宽度0可被用于迫使在一个字边界对齐。”

这只是意味着,编译器可以计算出有多少位被留在部分填充的字,并跳过到下一个单词的开头,就像我们通过在上面添加一个2位字段(假定我们知道a是30位并且字的大小是32)确保b在一个新单词中开始,我们可以...

struct X 
{ 
    int a : 30; 
    int : 0; // unnamed field 
    int b : 4; 
}; 

...并且编译器会为我们找出2这个w ay,如果我们将a更改为其他大小,或者最终编译为64位字大小,编译器将自动调整为适当的行为,而不需要手动更正未命名的字段。