编译器颠倒了 C 行顺序?
C line order reversed by compiler?
我有这个示例代码:
#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) 之前,但是当我 运行 代码时,它先询问字符串,然后再打印数字。我将 NetBeans 与 Cygwin gcc 编译器一起使用。有什么我想念的吗?是编译器错误吗?
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 行)计算 a
或 b
,因为它不会影响代码的行为。或者它甚至可以简单地将函数替换为:
void func(void)
{
printf("%d\n", 10);
}
通常情况下,编译器会出于优化目的进行此类转换,并且是允许的。在您的代码中,编译器无法执行此类代码转换,因为它会影响代码的可观察行为。
我有这个示例代码:
#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) 之前,但是当我 运行 代码时,它先询问字符串,然后再打印数字。我将 NetBeans 与 Cygwin gcc 编译器一起使用。有什么我想念的吗?是编译器错误吗?
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 行)计算 a
或 b
,因为它不会影响代码的行为。或者它甚至可以简单地将函数替换为:
void func(void)
{
printf("%d\n", 10);
}
通常情况下,编译器会出于优化目的进行此类转换,并且是允许的。在您的代码中,编译器无法执行此类代码转换,因为它会影响代码的可观察行为。