我想知道当我使用main
函数的返回值时会发生什么。
我发现如果我从main
返回一个数组变量(它应该是退出状态)并在shell中打印退出状态,那么输出总是56.我想知道为什么?
C程序:
int* main(void) {
static int x[3];
x[0]=89;
x[1]=15;
x[2]=10;
return x;
}
我按如下方式测试:
gcc array_return.c -o array_return
./array_return
echo $?
即使更改数组的大小或更改数组中的数字,输出也始终为56
。数字56
的含义是什么?
答案 0 :(得分:5)
你的程序返回一个指针。它不是"数组"正如你在问题中提出的那样。因为数组的名称求值为其第一项的地址(与数组本身的地址相同)。
在C中,main
函数返回的值被解释为exit status,即您示例中使用的$?
变量。
我想,你正在运行Bash shell,因为在Bash中,退出状态存储在$?
变量中。指针通常是一个大数字,至少大于 255 ,这是最大exit code in Bash:
超出范围退出值可能导致意外退出代码。出口 大于255的值返回模256的退出代码。例如, 退出3809给出退出代码225(3809%256 = 225)。
现在让我们通过打印变量的地址和地址modulo 256 修改您的程序:
#include <stdio.h>
int main(void) {
static int x[3];
printf("%ld ==> %d\n", (size_t)x, (size_t)x % 256);
return (int)x;
}
让我们编译并测试我是否正确:
$ gcc -Wall -g test.c -o test && ./test; echo $?
test.c: In function ‘main’:
test.c:6:12: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
return (int)x;
^
6295620 ==> 68
68
正如我们所看到的,返回状态等于6295620 % 256
,因为它在official documentation中有记录。
答案 1 :(得分:2)
根据ISO C,int* main(void)
不是实现需要支持的启动函数main
的形式之一。因此,行为不是由语言标准定义的。
int *main(void)
可以作为C实现提供的文档扩展。通过这种方式,C实现可以支持编写启动函数的其他方法。
更可能的是,构造是错误的,你的实现只是忽略了这种情况;它只是编译代码并让机器指令尽其所能。要了解实际行为,您必须了解该级别的情况。
很可能,返回的指针本身的按位表示被解释为整数终止状态值,转换为操作系统退出代码56.(可能是值中的某个位域,例如作为最低的8位,是56)。这假设int *
和int
以相同的方式从函数返回。他们可能不是。例如,在Motorola 68000系列处理器的C编译器中,存在通过A0寄存器返回指针和D0中的整数值的约定。因此,如果编写int *
返回函数以满足对预期返回int
的内容的外部引用,则调用程序将接收D0中发生的任何垃圾,而指针已进入A0。 / p>
由于未定义行为,因此无需进行诊断!在C语言中,您甚至可以写下这个:
int main[42] = { 3 };
在一些将编译和链接的环境中。执行时,阵列数据最终用作机器语言功能图像。 IOCC中出现了一次依赖此技巧的程序(可能不止一次):国际混淆C大赛。