C带返回值的void函数

C带返回值的void函数,c,C,据我所知,void函数中的return语句将抛出错误 但在下面的程序中,情况并非如此 此处显示的输出为1。怎么会这样 main() { int i=5; printf("%d",fun(fun(fun(i)))); } void fun(int i) { if (i%2) { return (i+(7*4)-(5/2)+(2*2)); } else { return (i+(17/5)-

据我所知,void函数中的
return
语句将抛出错误

但在下面的程序中,情况并非如此

此处显示的输出为
1
。怎么会这样

main()
{
    int i=5;
    printf("%d",fun(fun(fun(i))));
}

void fun(int i)
{
    if (i%2)
    {
        return (i+(7*4)-(5/2)+(2*2));
    }
    else
    {
        return (i+(17/5)-(34/15)+(5/2));
    }
}

由于各种原因,您提供的代码实际上在C99中无效,但最痛苦的原因如下:

foo.c:5:17: warning: implicit declaration of function 'fun' is invalid in C99 [-Wimplicit-function-declaration]
    printf("%d",fun(fun(fun(i))));
                ^
foo.c:8:6: error: conflicting types for 'fun'
void fun(int i)
     ^
foo.c:5:17: note: previous implicit declaration is here
    printf("%d",fun(fun(fun(i))));
                ^
请注意,如果您为
fun()
提供了一个函数原型(您确实应该这样做),那么您将得到一组不同的错误:

foo.c:7:25: error: passing 'void' to parameter of incompatible type 'int'
    printf("%d",fun(fun(fun(i))));
                        ^~~~~~

不带表达式的
return
语句:

void func(void) {
    return;
}
void
函数中完全合法。带有表达式的
return
语句的合法性取决于您使用的C语言版本

1990年的C标准规定:

带有表达式的返回语句不得出现在 返回类型为void的函数

该标准的1999版和2011版均规定:

不应出现带有表达式的返回语句 在返回类型为void的函数中。A
返回
没有表达式的语句只能出现在函数中 其返回类型为
void

这是一个约束,意味着编译器必须对任何违反它的程序发出诊断(可能是非致命警告)

出于历史原因,C90允许在非void函数中使用不带表达式的
return
语句。前ANSI C没有
void
关键字,因此无法定义不返回值的函数。程序员会忽略返回类型(默认为
int
),而直接忽略它。C90规则允许编译这样的旧代码而不会出错。您仍然可能无法从非
void
函数返回值;如果调用方试图使用(不存在的)结果,则程序的行为是未定义的。1999年的标准稍微收紧了规则

程序的另一个问题是,在其声明可见之前调用
fun
。根据C99和更高版本的规则,这是非法的(尽管编译器可能只是对此发出警告)。根据C90规则,这是合法的,但编译器将假定函数返回
int
。程序的行为未定义,但您的
void
函数
fun
可能会恰巧表现为它返回了一个值,对它的调用可能恰巧表现为它使用了该值


C编译器往往对某些错误相当松懈,因此旧代码(有时在第一个实际标准发布之前编写)不会被拒绝。但是您的编译器至少应该警告您有关
return
语句的信息,可能还有关于无效调用的信息。您应该密切注意编译器警告;它们应该被当作致命错误来对待。您应该使用选项来增加编译器警告您的事情的数量。如果您使用的是gcc,请使用
-std=c90
-std=c99
-std=c11
,以及
-pedantic
来强制执行标准一致性。您可以添加
-Wall
-Wextra`以启用更多警告。

在原型出现之前使用
fun
可能会产生混乱的后果。这意味着它返回
int
,谁知道在以后定义它时编译器是如何解析的呢?从C99开始,这将被禁止。事实上,此代码段产生的编译器警告行数与相关代码行数相当。从来都不是好兆头,这是未定义的行为。我在没有编译器优化的情况下得到1,在编译器优化的情况下得到0。我不知道它是好是坏,但有时我在void返回函数中使用了很多“空”返回。@jewelstepher:这是非常有效的。虽然作为一个好的设计,有些人提倡写作功能,所以他们只从一个角度出发;早期的
return
s(带或不带值)会使控制流更难分析。