3

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

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

4 回答 4

4

因为您正在对调用未定义行为的指针执行指针算术NULL- 而这不需要崩溃。

于 2013-06-08T12:05:24.070 回答
2

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

于 2013-06-08T12:15:39.167 回答
1

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

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

ints 通常是 4 个字节长,所以如果ptr2有一个地址,比如说 10,那么ptr2->a也必须在地址 10,ptr2->b必须在 14,并且ptr2->c必须在地址 18。

因为 ptr2 是NULL,所以要加 4 到 member b,并且NULL+4=4。然后你添加 4ptr1并取消引用它,这让你ptr1成为b会员!

但这不是便携式的,你不应该这样做!

于 2013-06-08T12:17:33.190 回答
0

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

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

于 2013-06-08T13:13:40.003 回答