我正在学习 c99,在阅读了结构之后,我在 Linux 内核代码中发现了以下宏:
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
我..什么?用途:
#include <stdio.h>
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
struct book {
char title[100];
char author[100];
};
int main(void)
{
printf("%lu\n", FIELD_SIZEOF(struct book, title)); // prints 100
}
这是扩展(gcc -E)
printf("%lu\n", (sizeof(((struct book*)0)->title)));
真正让我困惑的是
0
。我将其替换为 1
、2
、+1
、-1
、+999
、'a'
和 "hello"
,并且 它始终有效。
来源中没有评论。我知道
->
用于通过指针访问结构体成员,但是((struct book*)0)
怎么能是指针呢?宏是如何工作的?
这里的关键是
sizeof
是编译器在编译时计算出来的。因此,您指定的指针实际上从未被取消引用。毕竟,物体所在的位置不会改变其大小。 sizeof
运算符将纯粹根据类型评估其操作数。
所以,你使用的地址实际上是无关紧要的,但是
0
(NULL
)是一个常见的选择。
sizeof(((t*)0)->f)
之所以有效,是因为
sizeof
被定义为不评估其参数(涉及 VLA 时有一些例外)。
(struct book*) 在这里是指针类型转换 0,所以,无论它是 0 或“a”还是其他什么,最终结果始终是指向 struct book 实例的指针。