

C语言函数void fun()和 void fun(void)有什么区别?
source link: https://blog.popkx.com/c%E8%AF%AD%E8%A8%80%E5%87%BD%E6%95%B0void-fun%E5%92%8C-void-funvoid%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C语言函数void fun()和 void fun(void)有什么区别?
相信C语言初学者常会在前辈留下的项目,或者一些开源项目中看到以 void 作为参数的函数,例如 void fun(void),虽然我们都明白在C语言中,“void”表示空,但是按理说,如果函数不需要参数,直接空着就行:void fun(),为什么还要多此一举的写上 void 呢?
C语言函数参数的定义方式
大多数C语言教程在谈到自定义函数时,一般都将函数的“参数类型列表”放在“()”中,例如:
void f(int a, float b){
...
}
C语言没有理由将“无参数函数”作为特例处理,因此从“通用性”来看,定义C语言函数时,“()”内应该始终有“参数类型列表”,如果函数不需要使用参数,应该指定为 void,而不是空着。
但是在C语言程序开发中,void fun(); 这种定义函数的方式又的确是可行的,难道C语言真的将“无参数函数”作为特例处理了吗?
其实不是的,在C语言中,定义函数时,指定参数还有另外一种方式(标识符列表方式):
void f(a, b)
int a;
float b;
{
...
}
以标识符列表方式定义函数不常见,但的确是可用的,下面是一段完整的测试C语言代码,请看:
#include <stdio.h>
void f(a, b)
int a;
float b;
{
printf("%d, %f\n", a, b);
}
int main()
{
f();
f(1);
f(2, 3.14);
return 0;
}
编译并执行这段C语言代码,得到如下输出:
# gcc t.c -Wall
# ./a.out
1, 0.000000
1, -inf
2, 3.140000
可见,以“标识符列表方式”定义C语言函数,在调用时,函数的表现很像不定参数函数,未明确传递值的参数的值是未定义的。
另外,定义C语言函数时,标识符列表可以省去,但是参数类型列表不可以。因此,void fun(); 这种定义函数的方式其实是“标识符列表”被省去的一种特殊。
正如前面所讨论的,以“标识符列表方式”定义的C语言函数表现很像不定参数函数,因此 void fun(); 定义的函数,传递给其任意多的参数都是允许的:
void fun()
{...}
fun();
fun(1,3,4); //合法
而 void fun(void); 这种指定参数类型列表的定义方式就不同了,它限制了 fun() 函数不能接收任何参数:
void fun(void)
{...}
fun();
fun(1,2,3); //非法
标识符列表方式定义函数
现在我们已经知道,以参数类型列表方式定义C语言函数时,“()”内必须指定参数类型——如果不需要参数,需要指定其为 void。
因此,void fun(); 这种定义方式其实是以标识符列表方式定义的,只不过参数的类型和数目被省去了,因此调用者在调用 fun() 函数时,必须事先知道参数类型和数目。
如果传递给函数的参数是任意的(这对于以“标识符列表方式”定义的函数是允许的),那么就可能导致函数出现不预期的行为。例如函数的堆栈可能会被破坏,因为编译器并不限定传递的参数个数,函数在获得控制权后可能会出现不同的内存布局。
一般不推荐使用“标识符列表”方式定义C语言函数,这种方式在以前比较流行,如今有一些存在于许多历史遗留的代码中。
参数类型列表方式定义函数
以参数类型列表方式定义C语言函数是今天的主流,这种方式更加安全,因为它严格限定调用者传递给函数的参数类型和个数。例如 void fun(void); 函数在被调用时,只能以无参数方式调用 fun()。
另外,以参数类型列表方式定义的C语言函数,编译器能够准确知道参数的数据类型,因此函数可以对接收到的参数做隐式的类型转换,还可以对参数做一些类型提升(即所谓的默认参数提升),例如 char 类型提升为 int。
顺便说一下,如果某个源文件中出现了省略的标识符列表方式定义的函数,和参数列表方式定义的函数,那么C语言原型将以参数列表方式定义的为准,请看下面这段C语言代码:
void f();
void f(int a)
{
...
}
原因也是简单的,void f(); 定义的函数 f() 可以接收任意多的参数,而 void f(int a); 定义的函数 f() 只能接收一个 int 型的参数,编译器为了不违背二者,只好让函数 f() 只接受一个 int 型参数了。
阅读更多: C语言
Recommend
-
15
作者:Mattt, 原文链接 ,原文日期:2018-10-31 译者: zhongWJ ;校对: nu...
-
17
TL;DR Prefer f(void) in C to potentially save a 1B instruction per function call when targeting x86_64 as a micro-optimization. -Wstrict-prototypes can help. Doesn’t m...
-
32
If you come from traditional, strongly typed languages you might be familiar with the concept of void: A type telling you that functions and methods return nothing when called. void exists in both JavaScript as a...
-
32
-
9
C语言const的使用,const修饰指针时,const char*,char const*和char* const有什么区别? 发表于...
-
7
C语言:什么是C语言函数 - OSCHINAtcxu 昨天 12:28 函数(function), 是一段可以...
-
8
c语言宏定义与普通函数接收参数的区别--值得注意 ...
-
6
TypeScript 中类型 any,void,unknown,never之间的区别 TypeScript 拓展了 JavaScript 的基本类型与语言特性,为了覆盖类型检查的情景,衍生出了一些额外的类型,其中 any,
-
6
V2EX › Go 编程语言 go 语言泛型多态和接口多态有什么区别
-
9
V2EX › Python 函数调用 return func 和 return result 有什么区别吗?
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK