作者:zjjj-jz政 | 来源:互联网 | 2022-12-08 16:50
C标准的哪个版本(如果有的话)是如何明确定义的?
void foo(void) {
char *nullPtr = NULL;
&*nullPtr;
}
请注意,我没有将结果分配给任何东西 - 第二行是一个简单的语句.
这应该是一个有明显答案的问题,但是(就像在这些问题上看似经常发生的那样)我听到的同样有很多人说答案"明显未定义"为"明确定义".
在一个相当相关的说明,以下是什么?应该foo
产生一个c?
extern volatile char c;
void bar(void) {
volatile char *nOnnullptr= &c;
&*nonnullptr;
}
(相同问题的C++版本:在C++中是否&*NULL定义良好?)
1> ex nihilo..:
虽然尝试取消引用空指针会导致未定义的行为,但这*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,那么标准的作者可能没有考虑过实现可能会做的其他情况.我认为,这里的一个难点是标准缺乏术语描述......
...什么构造像`&structArray [i ++].member`或`structArray [i ++].member = 2;`使用子表达式`structArray [i ++].member`,以及该动作的结果是什么(在应用`&`或`=`之前).对子表达式的评估将读取`member`的内容,但这不会发生; 因此,子表达式不会被"评估".鉴于术语"左值"用于指代*源代码*表达式,我会说表达式"解析"为"lref".当'p`是空指针时**p`的*evaluation*会调用UB,而解析表达式则不应该.