返回类型为void的表达式是否合法?

71
这个编译没有任何警告。
在C和C++中,这是合法的吗?还是只在gcc和clang中有效?
如果合法的话,是C99之后的新特性吗?
void f(){}

void f2(){
    return f();
}

更新

正如“Rad Lexus”建议的那样,我尝试了这个:

$ gcc -Wall -Wpedantic -c x.c 
x.c: In function ‘f2’:
x.c:7:9: warning: ISO C forbids ‘return’ with expression, in function returning void [-Wpedantic]
  return f();

$ clang -Wall -Wpedantic -c x.c 
x.c:7:2: warning: void function 'f2' should not return void expression [-Wpedantic]
        return f();
        ^      ~~~~~
1 warning generated.

$ gcc -Wall -Wpedantic -c x.cc
(no errors)

$ clang -Wall -Wpedantic -c x.cc
(no errors)

更新

有人问这个结构如何帮助。嗯,它更多或多少是一种语法糖。这里有一个很好的例子:

void error_report(const char *s){
    printf("Error %s\n", s);
    exit(0);
}

void process(){
   if (step1() == 0)
      return error_report("Step 1");

   switch(step2()){
   case 0: return error_report("Step 2 - No Memory");
   case 1: return error_report("Step 2 - Internal Error");
   }

   printf("Processing Done!\n");
}

9
已投票重新开放;提出的重复问题只涉及C++。这也被标记为C。(在void的使用上,C和C ++有很大的不同)。 - Bathsheba
16
所以你是在询问使用C还是C++?选择一种语言。 - 2501
8
注意:使用gcc -Wall -Wpedantic -std=c99-std=c11编译时,会收到警告:"warning: ISO C forbids 'return' with expression, in function returning void [-Wpedantic]"。 - Jongware
11
@HolyBlackCat: 我可以同时询问关于C、C++和Java吗?;-) - DevSolar
7
@DevSolar :D 好的,我会更清晰地表达。在我看来,询问C和C++中存在的功能是合理的,通常这些功能在两种语言中的行为方式相似。如果不相似,一个好的回答应该描述它们之间的差异。 - HolyBlackCat
显示剩余11条评论
5个回答

77

C11, 6.8.6.4 "The return statement":

在返回类型为void的函数中,return语句后面不应该跟表达式。

不可以使用表达式,即使它是void类型。

从同一文档的前言中可知:

第二版中的主要更改包括:

[...]

  • return没有表达式时不允许出现在返回值的函数中(反之亦然)

因此,这是C89->C99(语言标准的第二版)的变化,并一直保持至今。


C++14, 6.6.3 "The return statement":

具有非void类型的表达式的return语句只能用于返回值的函数[...]. 具有void类型的表达式的return语句只能用于带有cv void返回类型的函数; 表达式在函数返回给其调用者之前计算。

可以使用表达式,但仅限于void类型(自C++98以来就已经有效)。


7
@Lundin:模板?我猜是这样。看起来C99也允许了这种行为,而C ++可能只是复制了这种行为。 - DevSolar
1
@Lundin:Pfff... 别问我,我不指定标准,我只实现它。;-) (这就是为什么我随手准备了PDF并大致知道要查找的位置。) - DevSolar
10
在C++中,这主要适用于模板。如果ff2的返回类型是模板的参数,并且可以编写return f();而不必特别处理void,那么将很方便。(显然,这个特定的示例代码实际上不能作为模板 - 但对于更复杂的代码,它可能会很有用 - 例如看一下futures相关的东西。) - Martin Bonner supports Monica
3
正如Mohit的答案引用的那样,“在返回值的函数中不允许使用没有表达式的返回”这个问题是在前言第7段“第二版的重大变化”下提到的,而不是第6段“本第三版...[m]ajor changes”中。第二版是C99,它只改变了C89/90中没有表达式的返回;自C89/90中void首次被引入以来,在void函数中有表达式的返回就被禁止了。在C99之前,非void函数中没有表达式的返回和调用程序尝试使用该值是未定义行为。 - dave_thompson_085
2
特别是在函数同步执行的情况下,成员只需return external_function(args...); - Martin Bonner supports Monica
显示剩余11条评论

16

这段代码在C++中是允许的,但在C中不允许。

根据cppreference中Return statement的说明:

在返回void的函数中,返回带表达式的语句可以使用,如果表达式类型为void。


然而,在C11规范草案n1570中:

第二版的主要变化包括:

不允许在返回值的函数中使用没有表达式的返回语句(反之亦然)

(void类型函数中不允许带表达式的return)

6.8.6.4 return也有相应的对应内容:

表达式的返回语句不得出现在返回类型为void的函数中。仅当函数返回类型为void时,不带参数的返回语句才能出现。

(即使表达式的值为void,也不能出现不带参数的return语句。)


最好引用C++标准,并可能记录允许使用该构造的版本。cppreference不是非常可靠的来源,许多代码示例存在错误。 - chqrlie
@chqrlie,你能给我一个链接,其中包含在en.cppreference上代码示例错误的页面吗? - Mohit Jain
@MohitJain:只是一个例子:http://en.cppreference.com/w/c/string/byte/strncat 使用gcc 4.6编译: main.cpp:31:1: warning: control reaches end of non-void function [-Wreturn-type]。这不是C99以来的错误,但是这种写法很糟糕。 - chqrlie
@chqrlie 谢谢。我没有 C++ 规范,每当需要时,我会使用最新的草案和 en.cppreference 作为参考。 - Mohit Jain
1
@MohitJain:C++的最新草案已经非常接近了。实际上,源代码可以在Github上找到!我希望C和C++标准可以免费公开。cppreference文档非常完善,我的早期判断可能是基于法语翻译的印象。任何可见的错误都可以在发现时进行修复。 - chqrlie

5

C++允许类似这样的操作:

void f() 
{
    return void();
}

C语言不支持这种写法。所以如果你用ISO C编译它而非ISO C++,就会收到警告提示。表达式如下:

返回类型为void的表达式只能在返回cv void类型的函数中使用。


1
看起来是正确的,但最好提供两个声明的标准参考。 - HolyBlackCat

3
ISO/IEC 9899:201x委员会草案规定如下:
6.8.6.4返回语句
限制条件
1.带有表达式的return语句在返回类型为void的函数中不应出现。
2.没有表达式的return语句只能出现在返回类型为void的函数中。
因此,在C语言中这是被禁止的。
你需要使用-pedantic开关来让gcc检查标准违规。
test.c: In function ‘f2’:
test.c:6:12: warning: ISO C forbids ‘return’ with expression, in function returning void 
            [-Wpedantic]
     return f();

1

标准C不支持这种构造方式:

C11 6.8.6.4: return语句

限制条件

1. 在返回类型为void的函数中,return语句不得带表达式。在返回类型为void的函数中,return语句只能出现没有表达式的情况。

对于提问中的特殊情况,标准并未做出特别规定。一些C编译器支持此种扩展(例如gcc),但C11及之前版本认为其违反了约束条件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接