【问题标题】:C line order reversed by compiler?编译器反转C行顺序?
【发布时间】:2015-12-03 12:33:21
【问题描述】:

我有这个示例代码:

#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;
}

您可以看到 printf 在gets(s)之前,但是当我运行代码时,它首先询问字符串,然后打印数字。我正在使用带有 Cygwin gcc 编译器的 NetBeans。有什么我想念的吗?是编译器错误吗?

【问题讨论】:

  • 如果您运行它并输入超过 99 个字符的字符串,您错过了关于未定义行为的部分。
  • 这一行:int addOne();不正确,应该是:int addOne( int );
  • 函数:gets() 已被贬值,并在最新标准中被完全删除。建议使用fgets()
  • 发布的代码无法干净地编译。编译时,始终启用所有警告,然后修复这些警告。 (对于 gcc,至少使用:-Wall -Wextra -pedantic)例如,编译器会发出警告: 1)未使用的参数 argc 2)未使用的参数 argv[] 3)不要使用已弃用的函数 gets()

标签: c stdio


【解决方案1】:

printf() 通常是行缓冲的。所以 printf 的输出在缓冲区被刷新之前不会出现在屏幕上。

\n 添加到 printf 中,它应该可以按预期工作。

printf("%d\n",x);

如果不需要缓冲,您可以使用 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);
}

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

void func(void)
{
   printf("%d\n", 10);
}

通常,编译器会出于优化目的进行此类转换,并且是允许的。在你的代码中,编译器不能做这样的代码转换,因为它会影响你代码的可观察行为。

【讨论】:

  • 谢谢。使用\n 本身不起作用,只能使用setbuf(stdout, NULL)。在printf 之后调用fflush(stdout) 也可以。
  • fflush(stdout); 绝对是一个很好的解决方案。当您希望在尝试定位难以捉摸的错误时确保将调试消息同步写入控制台时,也可以使用它。
猜你喜欢
  • 2010-09-05
  • 1970-01-01
  • 1970-01-01
  • 2014-01-09
  • 1970-01-01
  • 2013-07-15
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多