我有这个奇怪的问题,我真的不知道我们为什么会发生这种情况。注意:这些程序在centOS的bash命令行中执行。
我有两个类似的C程序,它们是:
文件1.c
# include <stdio.h>
int main()
{
int a, b;
printf("Enter two nums\n");
scanf("%d %d", &a, &b);
printf("%d", a + b);
}
file2.c与file1.c相同,但在第二个printf
行中,格式字符串的末尾为\n
。
它们是使用gcc file1.c
和gcc file2.c
编译的。
据我所知,如果一个C程序成功执行,并且没有错误或使用return(X)的特定退出代码,程序应该返回0,因此退出代码为0。
但是对于这两个文件,当我运行它们(并输入2个数字以满足scanf
)时,我分别得到退出代码2和3。
进一步查找这些代码,我发现退出代码2意味着“误用shell内置程序”,我不知道为什么会发生这种情况。至于退出代码3,我没有找到任何具体的东西,但由于它不是零,它表明某种错误,这再次表明,我似乎不能在这些短程序中找到错误。
我输入的输入使用键盘。例如'2[Enter]2[Enter]'和检查退出代码使用echo $?
的权利后运行的程序(后他们被编译当然)。看起来像这样。
$ ./a.out
Enter two nums
2
2
4$
重要说明:我不能在这些程序中添加“返回0”,我把它们作为最终产品,然后对它们的输出做一些操作。所以我不能真正改变这些程序的任何东西。
希望你能在这个问题上提供帮助。谢谢!
2条答案
按热度按时间ar7v8xwq1#
您得到的警告意味着您使用非常旧的GCC版本(最多4.9.4版)进行构建,该版本默认为符合C90标准的模式(带有GCC扩展)。
在C99标准中添加了
main
函数的隐式返回。因为
main
函数没有返回值,所以会出现 undefined behavior。有三种可能的解决方案:
1.升级到GCC的较新版本(未升级到12.1),其中默认至少为C99模式。
1.修改代码以添加
main
函数的显式返回值1.使用标志
-std=c99
构建,该标志告诉编译器根据C99标准构建vtwuwzda2#
C标准为
main()
函数做了一个特例,并指定在没有return
语句的情况下,该函数隐式返回0
。这是为C99添加的,以尝试解决非常常见的错误,并确保一致的退出代码,除非通过return
语句或对exit()
的调用显式提供。您的目标系统上的编译器似乎不符合这一规则,可能将
printf
调用的返回值留在main()
调用方期望返回值的寄存器中。这是一个试探性的解释,但在C99之前,该行为实际上是未定义,任何退出状态都可能产生。如果输入
10
和20
,printf
将输出30
并返回2
,即写入stdout
的字节数。如果在格式字符串后追加换行符,则相同的输入将生成3个字节,因此返回值为3
。在x86系统上,printf
的返回值在ax
、eax
或rax
寄存器中设置(在16位、32位和64位模式下)。如果在退出main
函数之前未更改该寄存器,启动代码将假定该值是在main
函数中设置的,并发出一个系统调用,以该值作为退出代码退出程序。C启动的行为就像main()
被作为exit(main(argc, argv, envp))
调用一样。添加一个
return 0;
语句是解决这个问题的正确方法。升级编译器也应该可以解决这个问题。实际上非常令人惊讶的是,gcc不会添加隐式的return 0;
语句,您一定使用了非常旧的版本或者隐藏在同一命令行后面的不同编译器(clang在macOS中可以这样做,但符合C99标准)。关于 ,我发现退出代码2表示“误用shell内置程序”:这只是shell用于其内部命令的约定。退出状态的含义是约定问题,应该在程序的手册页中说明,但实际的退出状态只是其
main
函数(显式或隐式)的返回值,或者是终止程序的exit()
调用的参数(或_exit()
、_Exit()
、quick_exit()
...)