为什么此C片段中的NULL de-reference不会导致未定义的行为

时间:2016-09-09 10:29:35

标签: c pointers gcc struct c-preprocessor

我遇到了一段代码,其中NULL是对结构指针类型((foo *)0)->m的类型转换,并且该指针取消引用成员&(((foo *)0)->m)),并使用该((unsigned int)(&(((foo *)0)->m)))的地址并键入将其转换为整数以获取该成员在结构中的内存索引。#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; }

据我所知,NULL指针取消引用应始终导致C中的分段错误。但我不明白如何将NULL指针解除引用,并且仍然不会导致分段错误。

<div class="row">
    <div class="col-sm-2 reference">
        <a href="#"><img class="img-responsive" src="img/logo section/final/faded/adelie.png" alt="Adelie"></a>
    </div>
    <div class="col-sm-2 reference">
        <a href="#"><img class="img-responsive" src="img/logo section/final/faded/amageme.png" alt="Amageme"></a>
    </div>
    <div class="col-sm-2 reference">
        <a href="#"><img class="img-responsive" src="img/logo section/final/faded/bakey.png" alt="Bakey"></a>
    </div>
    <div class="col-sm-2 reference">
        <a href="#"><img class="img-responsive" src="img/logo section/final/faded/byensdepot.png" alt="Byensdepot"></a>
    </div>
    <div class="col-sm-2 reference">
        <a href="#"><img class="img-responsive" src="img/logo section/final/faded/dialoogle.png" alt="Dialoogle"></a>
    </div>
    <div class="col-sm-2 reference">
        <a href="#"><img class="img-responsive" src="img/logo section/final/faded/drachmann.png" alt="Drachmann"></a>
    </div>
</div>

1 个答案:

答案 0 :(得分:2)

C11标准在 6.5.3.2地址和间接运算符

中说明
  

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

(强调我的。)脚注说:

  

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

有趣的是,->运营商也不例外。我不知道这是故意做的还是是疏忽的。因此,在严格解释标准时,我会说&(((foo *)0)->m) 是未定义的行为。但这并不意味着程序必须崩溃或者编译器必须抱怨。

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