为什么使用getchar会导致printf停止工作?

3
我编写了一个程序,它接受一个字符输入,并输出该字符,就像这样:
int ch = getchar();
printf("%c", ch);

它按照我的预期工作。然后我决定更加友好,先打印Hello

printf("Hello!\n");
int ch = getchar();
printf("%c", ch);

令我惊讶的是,这导致编译器抛出了两个错误:

错误 C2065: 'ch' : 未声明的标识符
错误 C2143: 语法错误 : 缺少 ';' 在 'type' 前

我不明白为什么添加第一行会导致发生这种情况。无论如何,我重构了程序以消除int声明,错误神奇地消失了。
printf("Hello!\n");
printf("%c", getchar());

发生了什么?是什么神奇的东西导致这些错误出现,然后又消失了呢?

1
你使用的编译器是什么?这段代码在gcc 4.4.3上运行没有错误。 - Adam Cadien
@AdamCadien 我正在使用随 Visual Studio 2010 一起提供的任何版本的 MSVC。 - Peter Olson
4个回答

5

如果您使用较旧的 C 编译器,则必须在任何其他代码之前先声明所有变量。请尝试:

int ch;
printf("Hello!\n");
ch = getchar();
printf("%c", ch);

事实上,在1985年之前的C编译器要求在任何可执行语句之前,必须先在作用域({})中声明所有变量。如果仍有编译器这样做,那么可以轻松地使用任何优秀的免费编译器(例如gcc)进行替换。 - wallyk
@PeterOlson:应该可以。只有非常旧的MSC版本才会出现这种错误。也许还有其他问题,比如缺少分号? - wallyk
@wallyk:我认为微软非常不愿意采用C99,因为更多的开发人员使用C++,并且更喜欢采用C++11。 - dreamlax
@dreamlax:Naw:即使是1988年的MSC版本也可以很好地接受该结构。虽然我曾经被微软编译器的许多“质量控制”和“错误功能”问题所困扰,但落后于事实上的语言标准并不是其中之一。 - wallyk
1
Microsoft Visual C支持ANSI C89,而不是C99。您必须将声明放在函数/块的开头。抱歉。 - librik
显示剩余2条评论

3
在C89标准中,不允许在块开始后创建新变量,但在更新的C99标准中是允许的。 您正在使用旧版本编译器或不完全符合c99标准的编译器。
您给出的代码示例应该可以在任何好的编译器上运行,gcc-4.3.4上可以运行

解决方案:

有两种方法可以消除问题:
在块的开头声明变量:

int ch;
printf("Hello!\n");
ch = getchar();
printf("%c", ch);

或者

创建一个新的块用于声明变量:

printf("Hello!\n");
{ 
    int ch = getchar();
    printf("%c", ch);
}

建议:

您应该更改编译器,因为如果我没记错的话,即使在c99之前,gcc也支持此作为编译器扩展功能。


2

C99之前的C版本不允许“混合声明和代码”,这意味着您必须在作用域的开头声明所有变量。现代C编译器和C++编译器允许混合声明和代码。一些非C99编译器甚至可以将其作为扩展来使用。

我认为这是为了使编译器更容易确定堆栈实际上需要多少空间,或者类似的原因。


0

可能你正在使用一个相当古老的C编译器。可能是支持C89标准的编译器。 这会强制你在块的任何部分(例如函数或主函数)之前声明任何变量。 有两种解决方法: 首先声明ch:

int ch = getchar();
printf("Hello!\n");
printf("%c", ch);

或者,更好的方法是尝试更改编译器。您使用的操作系统是什么?Windows?Linux?Mac?

另外,一个快速提示。您正在使用getchar获取整数。

尝试使用scanf("%d", &ch)代替getchar。或者,如果您真的需要使用getchar,并将其打印为char,请将ch声明为char本身,并且如果您需要再次将其用作整数,请使用itoa函数将char转换为整数。


这个回答没有任何意义,getchar()返回的是int,所以chint也是有意义的。另外,你不需要使用itoa()int转换为char - dreamlax
我认为你没有理解我使用itoa()的意思。如果他真的需要(在代码中某些原因)将ch作为char而不是int使用,他可以使用itoa()将char转换回整数。 - Arthur Camara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接