正如标题所说,
一个典型的答案是:
允许任何和所有代码转换不会改变程序的可观察行为的规则
我们会不时地从某些实现中获取行为,这些行为归因于此规则.好多次错了.那么,这个规则究竟是什么呢.标准没有明确地将此规则作为一个部分或段落提及,那么究竟什么属于这条规则的范围?对我来说,这似乎是一个灰色区域,标准没有详细定义.有人可以根据标准的参考资料详细说明细节.
注意:将其标记为C和C++,因为它与两种语言都相关.
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定义良好?)
我在这里读到,如果编译器memset知道传递的内存缓冲区永远不再使用,则可以自由删除调用.怎么可能?在我看来(从核心语言的角度来看)memset只是一个常规函数,编译器无权假设其中发生的任何事情都没有副作用.
在链接文章中,他们展示了如何删除Visual C++ 10 memset.我知道Microsoft编译器在标准合规性方面并不领先,所以我问 - 它是按照标准,还是仅仅是msvc-ism?如果符合标准,请详细说明;)
编辑: @Cubbi
以下代码:
void testIt(){
char foo[1234];
for (int i=0; i<1233; i++){
foo[i] = rand()%('Z'-'A'+1)+'A';
}
foo[1233]=0;
printf(foo);
memset(foo, 0, 1234);
}
Run Code Online (Sandbox Code Playgroud)
在mingw下用线编译:
g++ -c -O2 -frtti -fexceptions -mthreads -Wall -DUNICODE -o main.o main.cpp
g++ -Wl,-s -Wl,-subsystem,console -mthreads -o main.exe main.o
objdump -d -M intel -S main.exe > dump.asm
Run Code Online (Sandbox Code Playgroud)
给出输出:
4013b0: 55 push ebp
4013b1: 89 e5 mov ebp,esp
4013b3: 57 push …Run Code Online (Sandbox Code Playgroud)