在 C 和 C++ 中返回 void 类型

Posted

技术标签:

【中文标题】在 C 和 C++ 中返回 void 类型【英文标题】:Return void type in C and C++ 【发布时间】:2016-06-29 11:43:42 【问题描述】:

编译时没有任何警告。

这在 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");

【问题讨论】:

投票重新开放;建议的副本仅适用于 C++。这也被标记为 C。(C 和 C++ 在使用 void 方面有很大不同)。 所以你要的是 C 还是 C++?选择一种语言。 注意:使用gcc -Wall -Wpedantic -std=c99-std=c11,您会收到警告:“警告:ISO C 禁止在函数返回 void [-Wpedantic] 中使用表达式'返回'”。 @HolyBlackCat:我可以同时询问 C、C++ 和 Java 吗? ;-) @DevSolar :D 好吧,我会说得更清楚。 IMO 询问 C 和 C++ 中存在的功能是合法的。通常,这些功能在两种语言中的行为相似。如果不是,一个好的答案将描述差异。 【参考方案1】:

C11,6.8.6.4“return 声明”:

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

不行,你不能使用表达式,即使它是void 类型。

来自同一文档的前言:

第二版的主要变化包括:

[...]

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

所以这是从 C89 -> C99(语言标准的第二版)的变化,从那以后一直如此。


C++14,6.6.3“return 语句”:

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

是的,您可以使用表达式if它是 void 类型(从 C++98 开始就有效)。

【讨论】:

“带有 void 类型表达式的 return 语句只能在返回类型为 cv void 的函数中使用” 为什么有人想编写这样无意义的代码呢?而不仅仅是写void f2() f(); 。似乎在某个地方一定有它的理由,即使它是 C++? @Lundin:模板?我假设。看起来 @Lundin:在 C++ 中,主要用于模板。如果ff2 的返回类型是模板的参数,则无需特殊情况void 就可以编写return f(); 很方便。 (显然,这个特定的示例代码并不能真正用作模板 - 但对于更复杂的代码,它可能很有用 - 例如,请参阅futures 的东西。 正如 Mohit 的回答正确引用的那样,“返回值的函数中不允许不带表达式的返回”项位于前言第 7 段“second 版中的重大变化”下,而不是第 6 段“这第三版...... [m]jor changes”。第二版是C99,将C89/90改成返回表达式; void 函数中的 return with 表达式自 C89/90 以来被禁止,当时 void 首次引入。 C99 之前的@Lundin 在 non-void 函数中返回没有表达式并且尝试使用该值的调用者是 UB。 特别是在函数同步执行的情况下,成员只会return external_function(args...);【参考方案2】:

此代码在C++ 中允许,但在C 中不允许

来自Return statement @ cppreference

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


C11 规范草案 n1570 中的 OTOH:

第二版的主要变化包括:

在返回 a 的函数中不允许不带表达式的返回 价值(反之亦然)

return 的表达式不允许在返回 void 的函数中使用)

和 6.8.6.4 返回

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

(即使表达式的计算结果为void

【讨论】:

最好引用 C++ 标准和可能的文档,因为允许构造的版本。 cppreference 不是一个非常可靠的来源,许多代码示例都有错误。 @chqrlie 你能给我一个链接到代码示例正在拧@en.cppreference 的页面吗? @MohitJain:只是一个例子: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 谢谢。我没有 C++ 规范,我在需要时使用最新的草稿和 en.cppreference 供我参考。 @MohitJain:C++ 最新草案已经足够接近了。源代码实际上在 github 上可用!我希望 C 和 C++ 标准可以免费公开获得。 cppreference其实是有据可查的,我之前的判断可能反映了我对法语翻译的印象。任何可见的错误都可以在发现时进行修复。【参考方案3】:

C++ 允许这样的事情:

void f() 

    return void();

而 C 没有。这就是为什么如果您将其编译为 ISO C 而不是 ISO C++ 会发出警告。这正式描述为:

带有 void 类型表达式的 return 语句只能用于 返回类型为 cv void 的函数

【讨论】:

它看起来是正确的,但是两个声明的标准引用会很好。【参考方案4】:

ISO/IEC 9899:201x 委员会草案规定如下:

6.8.6.4 返回语句

约束

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

    没有表达式的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();

【讨论】:

【参考方案5】:

标准 C 不支持这种结构:

C11 6.8.6.4:return 声明

约束

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

没有针对问题中的特殊情况添加特殊规定。一些 C 编译器确实支持此作为扩展(gcc 支持,除非被指示符合 C 标准之一),但 C11 和以前的版本认为它违反了约束。

【讨论】:

以上是关于在 C 和 C++ 中返回 void 类型的主要内容,如果未能解决你的问题,请参考以下文章

C++基础---无返回值函数(void函数)

C++基本内置类型

c++如何用泛型控制返回值

当一个函数无返回值时,函数的类型应定义为啥

C++编程知识:什么是万能指针?详解C语言万能指针的妙用

VC6和VC7中判断函数是不是有void返回类型的方法