C 标准为什么以及在哪里允许编译此代码?它在哪里有用?
struct foo {
int : 12;
};
那将在 §6.7.2.1结构和联合说明符中
12) 没有声明符但只有冒号和宽度的位域声明表示未命名的位域。126
脚注解释了为什么存在这样的事情:
126未命名的位域结构成员可用于填充以符合外部强加的布局。
话虽如此,标准的同一部分(第 8 段)还指出:
如果 struct-declaration-list 不包含任何命名成员,无论是直接还是通过匿名结构或匿名联合,则行为未定义。
但是一些编译器(至少是 GCC 和 clang)允许这个作为扩展。
如果这是结构中唯一的位域,则使用会受到限制,但并非不可能像ouah说明的那样使用。
该标准继续以另一个“奇怪”:
作为一种特殊情况,宽度为 0 的位域结构成员表示不会将进一步的位域打包到放置前一个位域(如果有的话)的单元中。
该程序调用未定义的行为。
C 说:
(C99,6.7.2.1p7)“[...] 如果 struct-declaration-list 不包含命名成员,则行为未定义。”
现在一些编译器接受它作为扩展。这怎么可能有用?
例如对于 Linux 内核著名的BUILD_BUG_ON_ZERO
宏:
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
要查看此宏的作用,您可以查看此处。
好吧,根据语言规范,如果您的程序包含没有命名成员的结构类型,则行为未定义。(对于为什么它没有被官方认定为违反约束的问题,我没有立即回答。)在 6.7.2.1/7 中有说明
struct-declaration-list 是结构或联合成员的一系列声明。如果 struct-declaration-list 不包含命名成员,则行为未定义。
除此之外,这样的声明并不是真正“有用”,因为它产生的唯一东西是未定义的行为。