当一个函数被编译器(如GCC)内联到C中时,操作顺序是否保持不变?

当一个函数被编译器(如GCC)内联到C中时,操作顺序是否保持不变?,c,gcc,compiler-optimization,C,Gcc,Compiler Optimization,考虑以下代码: #include <stdio.h> int f1() { printf("foo"); } int f2() { int a; } int main() { int a = f1(), b = f2(); printf("\n%d\n", a); printf("\n%d\n", b); return 0; } 但是,在以下情况下 #include <stdio.h> int f() {

考虑以下代码:

#include <stdio.h>

int f1() {
    printf("foo");
}

int f2() {
    int a;
}

int main() {
    int a = f1(), b = f2();

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

    return 0;
}
但是,在以下情况下

#include <stdio.h>

int f() {
    printf("foo");
    int a;
}

int main() {
    int a = f();
    printf("\n%d\n", a);

    return 0;
}
而不是

foo
0
即使最后一条语句没有返回任何内容。 我假设在Howevverf2的定义中,由于函数没有返回任何内容,编译器隐式地添加了一个返回0;最后。然而,为什么f不会出现这种行为

我使用以下方法进行编译:

gcc-O0 a.c-o a.out 我假设在Howevverf2的定义中,由于函数没有返回任何内容,编译器隐式地添加了一个返回0;最后

这是不正确的。根据C标准,如果程序试图使用函数调用的值,但函数不使用return返回值,则该行为不在C 2018 6.9.1 12中定义。除了main是特殊的之外,5.1.2.3 1中的一条规则说它默认返回零

然而,为什么f不会出现这种行为

已经观察到,GCC的行为是这样的:如果非void函数中没有return语句,它将返回最后计算的表达式的值。我还没有看到这方面的文件,这不是你应该依赖的行为。部分原因是该规则不完整。例如,如果最后一个表达式的类型为double,但返回类型为int,则我们不希望该规则成立


在本例中,该行为导致f或f1返回3,因为其中最后一个计算的表达式是printfoo;,printf调用的值是打印的字符数,在本例中是三个。

函数不返回任何内容,代码具有未定义的行为。您认为隐式返回0的假设是错误的。编译器应该警告您没有任何返回语句。请始终在启用警告的情况下编译,并且在代码编译时没有警告之前不要接受代码。为了使警告添加到您的Gcc/CLAN编译字符串中,也考虑添加-WSHIFT来警告阴影变量。对于windows上的VS cl.exe,请使用/W3。所有其他编译器都有类似的选项。阅读并理解每个警告-然后去修复它。他们将确定任何问题,以及出现问题的确切路线。通过倾听编译器告诉您的内容,您可以学到很多。隐式返回0仅适用于main。所有其他函数在所有路径上都需要显式返回,除非它们返回void。@Mat:这实际上不是C标准中的规则。
foo
3
foo
0