kar*_*k A 6 c struct offsetof pointer-arithmetic null-pointer
我有这段代码.它似乎在这里取消引用空指针,但随后按位与结果和unsigned int.我真的不明白整个部分.它打算做什么?这是指针算术的一种形式吗?
struct hi
{
long a;
int b;
long c;
};
int main()
{
struct hi ob={3,4,5};
struct hi *ptr=&ob;
int num= (unsigned int) & (((struct hi *)0)->b);
printf("%d",num);
printf("%d",*(int *)((char *)ptr + (unsigned int) & (((struct hi *)0)->b)));
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是44.但它是如何工作的?
它实际上并不是取消引用空指针.你应该看看整个代码.代码说的是:取数字0,将其视为struct hi *,b在它指向的结构中选择元素,并获取该元素的地址.此操作的结果将是元素b从结构开头的偏移量.当你将它添加到指针时,你得到的元素b等于4.
这将为您提供结构b内字段的偏移量hi
((struct hi *)0)是一个指向hi结构的指针,从地址开始0.
(((struct hi *)0)->b)是b上述结构的字段
& (((struct hi *)0)->b)是上述字段的地址.因为hi结构位于地址0,所以这是b结构内的偏移量.
(unsigned int) & (((struct hi *)0)->b)是从地址类型转换为unsigned int,以便它可以用作数字.
你实际上并没有解除引用NULL指针.你只是做指针算术.
(((struct hi *)0)->b)由于您尝试访问禁止的内存位置,因此访问会给您带来分段错误.
使用& (((struct hi *)0)->b)不给你分段错误,因为你只取地址,即禁止内存的位置,但你没有试图访问所述位置.
这不是“与”,而是取右侧参数的地址。
这是一个标准的 hack,用于在运行时获取结构成员的偏移量。您将 0 转换为指向 struct hi 的指针,然后引用“b”成员并获取其地址。然后将此偏移量添加到指针“ptr”并获取 ptr 指向的结构体的“b”字段的实际地址,即 ob。然后将该指针强制转换回 int 指针(因为 b 是 int)并输出它。这是第二次打印。第一个打印输出 num,它是 4,不是因为 b 的值为 4,而是因为 4 是 hi 结构体中 b 字段的偏移量。这是 sizeof(int),因为 b 跟随 a,而 a 是 int...希望这是有道理的:)