C中的&*NULL定义良好吗?

TLW*_*TLW 25 c language-lawyer

C标准的哪个版本(如果有的话)是如何明确定义的?

void foo(void) {
    char *nullPtr = NULL;
    &*nullPtr;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我没有将结果分配给任何东西 - 第二行是一个简单的语句.

应该是一个有明显答案的问题,但是(就像在这些问题上看似经常发生的那样)我听到的同样有很多人说答案"明显未定义"为"明确定义".

在一个相当相关的说明,以下是什么?应该foo产生一个c?

extern volatile char c;

void bar(void) {
    volatile char *nonnullptr = &c;
    &*nonnullptr;
}
Run Code Online (Sandbox Code Playgroud)

(相同问题的C++版本:在C++中是否&*NULL定义良好?)

ex *_*ilo 44

虽然尝试取消引用空指针会导致未定义的行为,但这*nullPtr是非法的,&*nullPtr是完全明确定义的.根据C11标准草案中的脚注102:

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

这是因为对于一元&算子(§6.5.3.23)这一事实:

如果操作数是一元*运算符的结果,那么运算符和&运算符都不会被计算,结果就好像两个都被省略了,....

C99标准具有相同的语言,但这并未出现在C90标准中,而我对该标准的解读&*nullPtr确实会导致C99之前的实现中出现未定义的行为.

根据C90标准(§6.3.2.3):

一元&(address-of)运算符的结果是指向由其操作数指定的对象或函数的指针....

和:

一元*运算符表示间接....如果为指针分配了无效值,则unary*运算符的行为未定义.

奇怪的是,我没有看到在C99基本原理中对这种变化的任何讨论,尽管我可能只是找不到它.

  • 在许多情况下,C标准表示一般操作类调用UB,而没有费心列举具有质量实现应该识别的明显含义的特定情况.如果到目前为止每个编译器都将`&*p`视为屈服`p`而不考虑`p`是否为null,那么标准的作者可能没有考虑过实现可能会做的其他情况.我认为,这里的一个难点是标准缺乏术语描述...... (4认同)
  • ...什么构造像`&structArray [i ++].member`或`structArray [i ++].member = 2;`使用子表达式`structArray [i ++].member`,以及该动作的结果是什么(在应用`&`或`=`之前).对子表达式的评估将读取`member`的内容,但这不会发生; 因此,子表达式不会被"评估".鉴于术语"左值"用于指代*源代码*表达式,我会说表达式"解析"为"lref".当'p`是空指针时**p`的*evaluation*会调用UB,而解析表达式则不应该. (2认同)