0

我想知道当我使用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意思?

4

2 回答 2

5

您的程序返回一个指针。它不是您在问题中提出的“数组”。因为数组的名称计算为其第一项的地址(与数组本身的地址相同)。

在 C 中,从main函数返回的值被解释为退出状态,即$?您的示例中使用的变量。

我猜,您正在运行 Bash shell,因为在 Bash 中,退出状态存储在$?变量中。指针通常是一个大数字,至少大于255 ,这是Bash中的最大退出代码:

超出范围的退出值可能会导致意外退出代码。大于 255 的退出值会返回以 256 为模的退出代码。例如,退出 3809 给出的退出代码为 225 (3809 % 256 = 225)。

现在让我们通过打印变量的地址和以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,正如官方文档中所记录的那样。

于 2016-10-08T15:27:16.760 回答
2

根据 ISO C,不是需要实现支持int* main(void)的启动功能形式之一。main所以行为不是由语言标准定义的。

int *main(void)可以作为 C 实现提供的文档化扩展。通过这种方式,C 实现可以支持编写启动函数的其他方式。

更有可能的是,构造是错误的,而您的实现只是忽略了这种情况;它只是编译代码并让机器指令做他们可以做的事情。要了解实际行为,您必须了解该级别发生的情况。

很可能,返回的指针本身的按位表示被解释为整数终止状态值,它转换为操作系统退出代码 56。(也许值中的某些位域,例如最低 8 位,是 56)。那是假设int *andint以相同的方式从函数返回。他们可能不是。例如,在摩托罗拉 68000 系列处理器的 C 编译器中,存在通过 A0 寄存器返回指针和在 D0 中返回整数值的约定。因此,如果int *编写返回函数以满足对预期返回的事物的外部引用int,则调用者会收到 D0 中发生的任何垃圾,而指针已进入 A0。

因为没有定义行为,所以不需要诊断!在 C 语言中,你甚至可以这样写:

int main[42] = { 3 };

在某些将编译和链接的环境中。执行时,数组数据最终用作机器语言函数图像。IOCC: International Obfuscated C Contest 曾经(可能不止一次)出现了一个依赖这个技巧的程序。

于 2016-10-08T15:46:24.107 回答