为什么以下表达式不是(空指针)运行时错误?
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));
答案 0 :(得分:4)
因为您正在NULL
指针上执行指针算法,该指针调用未定义的行为 - 并且不需要崩溃。
答案 1 :(得分:2)
实际上,在GNU C中,&ptr2->b
而st *ptr2=NULL;
在结构中产生数据成员'b'的字节偏移量,这里是4
答案 2 :(得分:1)
不幸的是,取消引用空指针并不总是崩溃!有时它只是愉快地前进,访问无效的内存!
您可能会看到输出值“12”。当您取消引用指针时,编译器正在执行的操作是添加偏移量以获取成员的地址。
int
s通常为4个字节,因此如果ptr2
的地址为10,那么ptr2->a
也必须位于地址10,ptr2->b
必须在14岁,ptr2->c
必须在地址18。
由于ptr2为NULL
,因此添加4以获取成员b
,NULL
+ 4 = 4。然后你将{4}添加到ptr1
并解除引用,这会让你成为ptr1
的{{1}}成员!
但这不可移植,你不应该这样做!
答案 3 :(得分:0)
这是完全合法的用法,因为“获取地址” - 操作符实际上意味着:“不要加载/存储变量的值,只需给出你为访问它而计算的地址。”它在调用实际的未定义行为之前停止访问。
这是编程中的一种典型习惯用法,它实际上封装在offsetof()宏中(在linux中广泛使用),并且自此进入编译器本身以提供更有意义的错误消息。有关详细信息,请参阅http://en.wikipedia.org/wiki/Offsetof,即使我不同意有关该声明合法性的本文。