【问题标题】:Is it mandatory to use "return" and "void" in the functions in C?在 C 中的函数中是否必须使用“return”和“void”?
【发布时间】:2015-06-02 06:49:28
【问题描述】:

示例:

void Function(int Number)
{
   process.....

   **return;**
}

每个函数的末尾是否必须使用“return”?

示例 2:

void Function(**void**)
{
   process...
}

如果我没有收到任何值,是否需要在参数列表中使用“void”?

有人说不,有人说是。 什么是对 C 中编译器和最佳实践的完美理解?

【问题讨论】:

  • 当您使用 void 作为函数返回类型时,您不需要返回任何值。换句话说,如果你想返回一些东西,那么你应该使用特定的数据类型
  • 使用void时,表示没有要返回的值。所以你不必返回任何 valuereturn; 和什么都不返回一样好。当您不提及void 时,在某些编译器中默认为int,因此您将不得不return 一些东西。
  • 至于后半部分,这取决于您使用的标准。省略 void 作为参数默认为旧式 C 声明/
  • FWIW:我在函数声明和函数定义中都使用 void func(void) 和明确的 (void)。在函数声明中是必需的;省略void 意味着除了函数不是可变参数函数之外,您没有指定任何有关参数的数量和类型的信息,因此您必须包含(void) 以告诉编译器拒绝带参数的调用。因为它在声明中是必需的,所以我也在定义中使用它,主要是为了保持一致性,其次是因为我使用的编译器选项(GCC 和 -Wstrict-prototypes)需要它。

标签: c function return void


【解决方案1】:

当使用void 作为返回类型时,不需要编写return 语句,因为本质上 void 意味着不返回任何内容。但是,如果要显式退出函数,可以使用 return

void 作为参数并不是必须的,它只是表示没有传递任何参数。

【讨论】:

  • you can use void if you want to explicitly...你的意思是return吗?
  • @SouravGhosh:感谢您的指点 :) 。是的,我的意思是返回,不知道我在想什么。
  • 这只解决了一半的问题。 (void) 参数呢?
  • @Potatoswatter:感谢您帮助我改进我的答案:)
  • @AyushiJha 对于 C++,void 参数是正确的,但在 C 中,它可能有意义。目前,空参数列表在 C11 中已弃用(被视为“过时”,第 6.11.6 节)。
【解决方案2】:

return 用于void 函数的唯一真正原因是提前退出该函数。根据 C99 §5.1.2.2.3 程序终止,假定 main 没有 return 的返回值为 0

到达终止主函数的 } 返回值 0

但最好准确指定要返回的值。

作为对酷人评论的回应,以下代码使用 gcc 编译,并带有标志 -std=c89-std=c99-std=c11

#include <stdio.h>

int main(void) {
  printf("Hello world\n");
}

至于void 作为参数,通知C 编译器您使用的是新的函数声明样式而不是旧的样式。它在技术上可以省略,但要小心,void 是首选方法。

【讨论】:

  • "return 有时可以省略,但最好准确指定要返回的值。" ——不,这是一个错误。您得到的不是随机值,而是未定义的行为。它可能会崩溃。
  • @Potatoswatter 我专门引用了 main 函数,它确实可以省略
  • @cabellicar123 , main 的 C89,C99 和 C11 的返回语句可以省略吗?
  • @cabellicar123 ,我用 GCC 尝试了代码。当我使用-std=c89:In function 'main': warning: control reaches end of non-void function [-Wreturn-type] } 编译时它会发出此警告,并且在我使用 C99 或 C11 时不会发出任何警告。所以我猜想 C89 中需要 return 语句。
  • @CoolGuy:在 C99 和 C11 中,为了匹配 C++98 所做的决定,可以将 return 留在 main() 的末尾。在 ISO/IEC 9899:2011 中,§5.1.2.2.3 程序终止 如果main 函数的返回类型是与int 兼容的类型,则从初始返回调用main函数等效于以main函数返回的值作为参数调用exit函数;到达终止main 函数的} 返回值0。 C89/90 不包括“到达}”子句。
【解决方案3】:

根据 C 标准(6.7.6.3 函数声明符(包括原型)

  1. void 类型的未命名参数的特殊情况是唯一的 列表中的 item 指定该函数没有参数。

  1. 标识符列表仅声明参数的标识符 的功能。函数声明器中的一个空列表,它是一部分 该函数的定义指定该函数没有 参数。函数声明器中的空列表不是一部分 该函数的定义指定没有关于 提供参数的数量或类型。145)

脚注 145 指的是“未来方向 §6.11.6”和“使用带空括号的函数声明符(不是原型格式参数 类型声明符)是一个过时的特性。”

因此声明

void f( void );

表示该函数没有参数。

声明

void f();

表示参数的数量和类型未知。

声明同时是一个定义

void f()
{
}

表示该函数没有参数。

对于返回类型为void 的函数中的return 语句,如果它是函数的最后一条语句,则通常将其省略。使用最后一个 return 语句只会让代码的读者感到困惑,因为他必须确保 return 语句中缺少表达式不是拼写错误。

【讨论】:

  • 请注意,声明void f();的函数确实意味着参数的数量和类型未知,但数量是固定的——该函数不能是使用省略号...的可变参数函数参数列表。
  • “不能是可变参数函数”标准的相关部分是 §6.5.2.6 函数调用,¶6:如果表示被调用函数的表达式具有以下类型不包含原型,……如果函数定义的类型包含原型,并且原型以省略号 (, ...) 或……结尾,则行为未定义。
  • @Vlad “至于退货声明...”,您能否澄清、举例说明这一段?什么是混乱?我是菜鸟。
  • @Santropedro 可以执行返回类型为 void 的函数,直到遇到右大括号 }。
【解决方案4】:

参数中void的省略意味着函数接受任意数量的参数:

假设一个程序:

void func() {
}

void func2(void) {
}

int main(void) {
    func(2);
    func2(2);
}

现在用gcc -std=c11 -Wall -pedantic test.c 编译它,你只会从func2 得到错误:

test.c: In function ‘main’:
test.c:9:5: error: too many arguments to function ‘func2’
     func2(2);
     ^
test.c:4:6: note: declared here
 void func2(void) {

也就是说,使用参数调用void func();不是GCC的编译时错误,而使用参数调用void func2(void)是编译时错误。即使该函数没有任何参数,仍然可以使用任意数量的参数调用它。

但是,即使这样编译,6.5.2.2 函数调用也会说“如果参数的数量不等于参数的数量,则行为未定义。” (并且func 使用 1 个参数调用,但没有参数)。


C11 标准 n1570 工作草案说明如下:

6.11.6 函数声明符

  1. 使用带空括号的函数声明符(不是原型格式参数 类型声明符)是一个过时的特性。

(有趣的事实:标准本身在其示例中使用int main())。


至于return 语句,如果它是最后一条语句,则可以从返回void 的函数中省略。 Return 有 2 种用途 - 终止函数的执行并指定返回给调用者的值。

标准草案说:

  1. 一个 返回 语句终止当前函数的执行并将控制权返回给 它的调用者。一个函数可以有任意数量的 返回 声明。

这里的任何意思都表示允许返回值的函数或不返回值的函数(返回void)有没有 return 语句。

函数声明草案中的 6.9.1 说:

  1. 如果 } 到达终止函数,并且函数调用的值由 调用者,行为未定义

因此,如果函数返回一个值(不是void),则省略 return 语句是未定义的行为,并且调用者使用该值。 (作为一个例外,该标准还规定,在 main() 中省略 return 语句现在相当于返回 0,这是一种指定行为。

【讨论】:

  • 关于“使用参数调用 void func(); 不是错误”:它会导致未定义的行为,因此是错误。然而,编译器不需要诊断问题,这就是为什么省略 void 是个坏主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 2018-06-23
  • 2014-04-18
  • 1970-01-01
相关资源
最近更新 更多