Ben*_*enj 11 c struct initialization
假设我有以下结构:
typedef struct
{
unsigned field1 :1;
unsigned field2 :1;
unsigned field3 :1;
} mytype;
Run Code Online (Sandbox Code Playgroud)
前3位将可用,但sizeof(mytype)将返回4,这意味着29位填充.我的问题是,标准保证的这些填充位是否由语句初始化为零:
mytype testfields = {0};
Run Code Online (Sandbox Code Playgroud)
要么:
mytype myfields = {1, 1, 1};
Run Code Online (Sandbox Code Playgroud)
这样,memcmp()假设位4..29为零,执行以下操作是安全的,因此不会影响比较:
if ( memcmp(&myfields, &testfields, sizeof(myfields)) == 0 )
printf("Fields have no bits set\n");
else
printf("Fields have bits set\n");
Run Code Online (Sandbox Code Playgroud)
Jen*_*edt 11
是的,不是.实际标准C11规定:
如果未显式初始化具有静态或线程存储持续时间的对象,则:
....
如果它是一个聚合,则根据这些规则初始化(递归)每个成员,并将任何填充初始化为零比特;
因此,这仅适用于静态存储的对象,在第一个视图中.但后来又说:
如果括号括起的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小的数组的字符串文字中的字符数少于数组中的元素,则聚合的其余部分应为隐式初始化与具有静态存储持续时间的对象相同.
因此,这意味着未明确初始化的子结构内的填充是零位初始化.
总之,结构中的一些填充保证是零位初始化,有些则不是.我不认为这种混淆是故意的,我会为此提交一份缺陷报告.
旧版本根本没有.因此,对于大多数现有的编译器,您必须更加小心,因为它们还没有实现C11.但AFAIR,clang已经为此做了.
另请注意,这仅适用于初始化.填充不一定要在分配时复制.
C99标准未指定填充位将设置为零.实际上,它特别提到任何填充位的值都是未指定的,因此不需要在赋值中复制填充.
脚注51至6.2.6.1(6)(n1570):
因此,例如,结构分配不需要复制任何填充比特.
新的C2011标准 - 感谢Jens Gustedt分享这些知识 - 指定静态或线程存储持续时间的对象中的填充位而没有显式初始化被初始化为0.
仍无法保证作业.