通过NULL指针的结构成员的地址

时间:2013-06-08 12:01:12

标签: c pointers struct null

为什么以下表达式不是(空指针)运行时错误?

typedef struct{
           int a,b,c;
          } st;

st obj={10,12,15};
st *ptr1=&obj;
st *ptr2=NULL;

printf("%d",*(int *)((char*)ptr1+(int)&ptr2->b));

4 个答案:

答案 0 :(得分:4)

因为您正在NULL指针上执行指针算法,该指针调用未定义的行为 - 并且不需要崩溃。

答案 1 :(得分:2)

实际上,在GNU C中,&ptr2->bst *ptr2=NULL;在结构中产生数据成员'b'的字节偏移量,这里是4

答案 2 :(得分:1)

不幸的是,取消引用空指针并不总是崩溃!有时它只是愉快地前进,访问无效的内存!

您可能会看到输出值“12”。当您取消引用指针时,编译器正在执行的操作是添加偏移量以获取成员的地址。

int s通常为4个字节,因此如果ptr2的地址为10,那么ptr2->a也必须位于地址10,ptr2->b必须在14岁,ptr2->c必须在地址18。

由于ptr2为NULL,因此添加4以获取成员bNULL + 4 = 4。然后你将{4}添加到ptr1并解除引用,这会让你成为ptr1的{​​{1}}成员!

但这可移植,你不应该这样做!

答案 3 :(得分:0)

这是完全合法的用法,因为“获取地址” - 操作符实际上意味着:“不要加载/存储变量的值,只需给出你为访问它而计算的地址。”它在调用实际的未定义行为之前停止访问。

这是编程中的一种典型习惯用法,它实际上封装在offsetof()宏中(在linux中广泛使用),并且自此进入编译器本身以提供更有意义的错误消息。有关详细信息,请参阅http://en.wikipedia.org/wiki/Offsetof,即使我不同意有关该声明合法性的本文。