在C中明显的NULL指针取消引用实际上是指针算术吗?

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.但它是如何工作的?

Sta*_*asM 8

它实际上并不是取消引用空指针.你应该看看整个代码.代码说的是:取数字0,将其视为struct hi *,b在它指向的结构中选择元素,并获取该元素的地址.此操作的结果将是元素b从结构开头的偏移量.当你将它添加到指针时,你得到的元素b等于4.


Nat*_*man 6

这将为您提供结构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)不给你分段错误,因为你只取地址,即禁止内存的位置,但你没有试图访问所述位置.


MK.*_*MK. 3

这不是“与”,而是取右侧参数的地址。
这是一个标准的 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...希望这是有道理的:)

  • 好吧,当您请求 ((struct hi *)0)->b 时,您是在请求存储在地址 4 处的值,而您无权访问该值,而当您请求 & 时,您是在请求该值地址,为 4,并且是有效的计算。你可以谈论问题是什么,但你不能提出问题。 (2认同)