为什么这个C片段中的NULL取消引用不会导致未定义的行为 [英] Why does the NULL de-reference in this C snippet not cause undefined behaviour

查看:153
本文介绍了为什么这个C片段中的NULL取消引用不会导致未定义的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一段代码,其中NULL被类型转换为结构指针类型(foo *)0 ,并且该指针取消引用成员<$ c ((foo *)0) - > m ,并且使用&(((foo *)0) - > m) / code>并将其转换为整型,以获得结构中该成员的内存索引。((unsigned int)(&(((foo *)0) - > m)))

I came across a piece of code where NULL is typecast to an structure pointer type (foo *) 0, and with that pointer de-referencing a member ((foo *)0)->m, and using address of that &(((foo *)0)->m)) and type casting it to integer to get the memory index of that member with in the structure.((unsigned int)(&(((foo *)0)->m))).

据我所知,NULL指针解引用应该总是导致C中的段错误。但是我不明白NULL指针可以像这样去引用,并且不会导致分段错误。

To my knowledge NULL pointer dereference should always result a segmentation fault in C. But I don't understand how NULL pointer can be de-referenced like this and still not result in a segmentation fault.

#include <stdio.h>
#define  MACRO(m) ((unsigned int)(&(((foo *)0)->m)))

typedef struct
{
int a;
int b;
int c;
int d;
}foo;

int main(void) {
    printf("\n  %d  ", MACRO(c));
    return 0;
}


推荐答案

em> 6.5.3.2地址和间接运算符:

The C11 standard says in 6.5.3.2 Address and indirection operators:


一元&运算符产生其操作数的地址。如果操作数的类型为''type'',则结果的类型为'',指向类型''。 如果操作数是一元操作符*的结果,那么操作符和&运算符进行评估,结果就好像两个都被省略一样,除了运算符的约束仍然适用并且结果不是左值。同样,如果操作数是[]运算符的结果,那么,&运算符和[]所隐含的一元*进行评估,结果就好像是&运算符被删除,[]运算符被改为+运算符。否则,结果是一个指向由它的操作数指定的对象或函数的指针。

The unary & operator yields the address of its operand. If the operand has type ''type'', the result has type ''pointer to type''. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator. Otherwise, the result is a pointer to the object or function designated by its operand.

(强调我的)。脚注说:
$ b

(Emphasis mine.) And the footnote says:


因此,& * E等于E(即使E是空指针)

Thus, &*E is equivalent to E (even if E is a null pointer)

有趣的是, - > 运算符也不例外。我不知道这是故意做的还是这是一个疏忽。所以在严格的标准解释中,我会说&((((foo *)0) - > m) 是未定义的行为。不过,这并不意味着程序必须崩溃,或者编译器不得不投诉。

Interestingly, there's no exception for the -> operator. I don't know whether this was done deliberately or whether it is an oversight. So in a strict interpretation of the standard, I'd say that &(((foo *)0)->m) is undefined behavior. This doesn't mean that a program has to crash or that the compiler has to complain, though.

也就是说,在进行相同的异常时完全合理 - > 运算符的结果地址,这就是大多数编译器所做的。

That said, it's completely reasonable to make the same exception when taking the address of the result of an -> operator, and that's what most compilers do.

这篇关于为什么这个C片段中的NULL取消引用不会导致未定义的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆