我在/usr/include/linux/kernel.h中碰到了这个奇怪的宏代码:
/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
Run Code Online (Sandbox Code Playgroud)
怎么:-!!办?
可能重复:
实际使用零长度位域
为什么有些结构具有零宽度位域,为什么需要它?
struct foo {
int a:3;
int b:2;
int :0; // Force alignment to next boundary.
int c:4;
int d:3;
};
int main()
{
int i = 0xFFFF;
struct foo *f = (struct foo *)&i;
printf("a=%d\nb=%d\nc=%d\nd=%d\n", f->a, f->b, f->c, f->d);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上述程序的输出是
manav@os-team:~/programs/test$ ./a.out
a=-1
b=-1
c=-8
d=0
Run Code Online (Sandbox Code Playgroud)
请解释为什么这些值是负数,以及结构内部这些变量的内存布局?
我在C标准草案(n1570)中看到了以下示例:
$ 3.14第4段:宣布为以下结构:
struct
{
char a;
int b:5, c:11, :0, d:8;
struct
{
int ee:8;
} e;
}
Run Code Online (Sandbox Code Playgroud)
那么,什么:0意思呢?
我知道什么是字段,但:0没有名字,我不明白.
:0没有任何标识符的目的是什么?
Fount此语句零宽度位字段可以使下一个字段在下一个容器边界上对齐,其中容器的大小与位字段的基础类型相同
为了实现这一点,假设int是2个字节(16位),而short是1个字节(8位)以节省输入.另外,假设我们正在使用gcc编译器(很好地解释了与clang的差异).
struct foo {
unsigned int a:5;
unsigned int :0;
unsigned int b:3;
}
Run Code Online (Sandbox Code Playgroud)
在内存中,这看起来像
struct address
|
|
v
aaaaa000 00000000 bbb00000 00000000
Run Code Online (Sandbox Code Playgroud)
问题1:在我的理解它不会像aaaaa000 00000000 0..00bbb00000...,所以bbb必须与容器对准直接按照当前的容器.这是真的吗?
继续,如果我指定
struct bar {
unsigned short x:5;
unsigned int :0;
unsigned short y:7;
}
Run Code Online (Sandbox Code Playgroud)
会这样吗?
struct address
| short stops here short starts
| | |
v v | this is uint | v
xxxxx000 00000000 00000000 yyyyyyy0
Run Code Online (Sandbox Code Playgroud)
编辑1
有人指出短路不能少于16个字节.这与这个问题的观点略有不同.但是,如果对你很重要,你可以替换short使用char …