无效指令的解释

Interpretation of instructions without effect

我们如何解释下面的程序和它的成功?(很明显不能有任何错误信息)。我的意思是编译器如何解释 main 中的第 2 行和第 3 行?

#include <stdio.h>

int main()
{
int a,b;
a; //(2)
b; //(3)
return 0;
}

这就像你尝试这样的事情:

#include <stdio.h>

int main(void){
    1;
    2;
    return 0;
}

正如我们所见,这里有两个表达式,后跟分号(1; 和 2;)。根据语言规则,这是一个格式正确的语句。

没毛病,就是没用

但是,如果您尝试使用 though 语句(a 或 b),则行为将是不确定的。 当然,编译器会将其解释为无效的语句

L.E:

如果你运行这个:

#include <stdio.h>

int main(void){
int a;
int b;

printf("A = %d\n",a);
printf("B = %d\n",b);

    if (a < b){
        printf("TRUE");
    }else{
        printf("FALSE");
    }
    return 0;
}

您将获得:

A = 0 B = 0 FALSE

因为ab设置为0;

你的

a;

只是一个表达式语句。与在 C 中一样,对表达式语句中的完整表达式求值并立即丢弃其结果。

比如这个

a = 2 + 3;

是包含完整表达式 a = 2 + 3 的表达式语句。该表达式的计算结果为 5,并且还具有将 5 写入 a 的副作用。结果被评估并丢弃。

表达式语句

a;

以同样的方式治疗,只是没有副作用。 由于您忘记了初始化变量,对上述表达式的求值可能会正式导致未定义的行为。

显然,实用的编译器会完全跳过此类表达式语句,因为它们没有可观察到的行为。

C 中的句子不是控制结构(if、switch、for、while、do while)或控制语句(break、continue、goto、return)是表达式。

每个表达式都有一个结果值。
对表达式的副作用进行评估(更改对象的值、写入文件、读取易失性对象以及执行其中一些操作的函数)。

这种表达式的最终结果总是被丢弃。
例如,函数 printf() return 是一个 int 值,一般不使用。然而这个值产生了,然后被丢弃了。
但是函数 printf() 会产生副作用,因此必须对其进行处理。

如果一个句子没有副作用,那么编译器完全可以随意丢弃它。

我认为对于编译器来说,检查一个句子是否没有任何副作用并不难。因此,在这种情况下,您可以预期编译器将选择不执行任何操作。

此外,这不会影响程序的可观察行为,因此在程序执行结果中获得的内容没有区别。但是,当然,如果编译器完全忽略任何计算,程序将 运行 更快。

另请注意,在某些情况下,浮点环境可以设置标志,这被认为是副作用。

Standard C (C11) 表示,作为第 5.1.2.3p.4 段的一部分:

An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced [...]

结论: 必须阅读自己正在使用的特定编译器的文档。

这就是为什么你应该使用一些编译警告标志! -Wall 会触发 "statement with no effect" 警告。

如果您想查看编译结果,请使用 -S 进行编译。 用你的代码试试,with/without -O(优化)标志...