编译器反转C行顺序?

adt*_*ewa 3 c stdio

我有这个示例代码:

#include <stdio.h>
#include <stdlib.h>

int addOne();

int main(int argc, char** argv) {
    char s[100];
    int x = 1;
    x = addOne(x);
    printf("%d",x);
    gets(s);
    return (EXIT_SUCCESS);
}

int addOne(int j) {
    return j + 1;
}
Run Code Online (Sandbox Code Playgroud)

您可以看到printf在获取之前,但是当我运行代码时,它会在打印数字后首先询问字符串.我正在使用NetBeans和Cygwin gcc编译器.有什么我想念的吗?这是编译器错误吗?

P.P*_*.P. 12

printf()通常是行缓冲的.因此,在刷新缓冲区之前,printf的输出不会出现在屏幕上.

添加\n到printf,它应该按预期工作.

printf("%d\n",x);
Run Code Online (Sandbox Code Playgroud)

如果不需要,您可以禁用缓冲setbuf(stdout, NULL);.

顺便说一句,你永远不应该gets().请fgets()改用.因为gets()容易出现缓冲区溢出漏洞,并且自C99以来已被淘汰并且已从C11中完全删除.


关于你怀疑编译器正在重新排序这些行:编译器可以重新排序指令,并允许合法地执行此操作.但只要它不影响程序的可观察效果.

考虑以下代码,

void func(void)
{
   int a = 2;
   int b = 3;

   a = a * 2;  //line 1
   b = b + 3;  //line 2

   printf("%d\n", a+b);
}
Run Code Online (Sandbox Code Playgroud)

编译器可以计算任意ab以任何顺序(线1或2号线),因为它不会影响代码的行为.或者它甚至可以简单地用以下函数替换函数:

void func(void)
{
   printf("%d\n", 10);
}
Run Code Online (Sandbox Code Playgroud)

通常,编译器会进行此类转换以进行优化,并且是允许的.在您的代码中,编译器不能执行此类代码转换,因为它会影响代码的可观察行为.

  • 谢谢.使用`\n`本身不起作用,只使用`setbuf(stdout,NULL)`.在`printf`之后调用`fflush(stdout)`也正在工作. (2认同)