从声明为void的函数返回一个整数值

时间:2014-08-29 13:00:02

标签: c

以下程序在某些编译器上编译时没有错误(仅警告)。但我们可以预测其产量吗?如果是这样,怎么样?

#include<stdio.h>

void main()
{
    printf("%d",fun(5));
}

void fun(int i)
{
    if(i%2)
        return i;
    else
        return i+2;
}

1 个答案:

答案 0 :(得分:3)

是的,这个可以编译。不,无法安全执行

由于您没有在fun上声明main高于其使用率,因此默认为int返回类型和任意数量的参数。就像编译器添加了一样:

int fun(); // Implicit declaration for the function used below

void main()
{
        printf("%d",fun(5));
}

当编译器遇到你的定义时,它会根据这个隐式声明警告不匹配的声明和定义。

然后它会再次警告您从刚刚声明的函数void返回值。

请注意,它不会警告您使用void函数的返回值,因为当它在您的printf中连接fun调用时,它仍然只有fun的隐式声明。

您将收到有关main的返回类型的更多警告,该类型必须为int。然后编译结束&#34;成功&#34;。

但上述所有问题都是未定义行为的来源。你不应该这样做,并且编译器很友好地警告你(它没有被要求这样做)。如果执行生成的可执行文件,它可以完全执行任何操作。

我尝试了它并打印了#34; 1&#34;。也许你会打印&#34; 5&#34;。它可以印上马​​铃薯&#34;,或者让我的袜子着火,就标准而言。

底线是:不,我们无法预测具有UB的程序的输出或行为。

编辑:我不应该写,我不应该写,我不应该写...

所以你得到0或1.最有可能发生的事情:

  • 根据隐式声明,您的函数会像连接一样返回一个整数。
  • 在您的函数中,您的程序计算数字的2模数,并将结果存储在寄存器中。
  • 然后尝试返回一个值。但编译器知道void函数不会返回任何内容。所以它忽略了你在return之后所写的内容。
  • 执行从您的功能返回。如上所述,您的函数连线为返回int,因此调用代码会获取它所认为的#34;是你的回报价值。并且恰好将int - returing函数的返回值存储在先前使用的寄存器中。因此,调用代码获取模数值。

你的问题正在受到严厉对待,因为编辑一直在骂你,你在写胡言乱语。

但它仍然很有趣,因为编译器通常不会警告UB,并且可能导致不可预测且难以跟踪的错误。了解他们可能的来源可以帮助您。但是从不依赖于你在这些实验中发现的东西。