在C语言中void
type 的引入比“null”或“nothing”更具有“不关心”的含义,并且它用于不同的范围。
The void
关键字可以引用void type
, a reference to void
, a void expression
, a void operand
or a void function
。它还显式定义了一个没有参数的函数。
让我们看一下其中的一些。
The void
type
首先void
对象存在并具有一些特殊属性,如中所述ISO/IEC 9899:2017,§6.2.5 类型:
- void 类型包含一组空值;它是一个不完整的对象类型,无法完成。
Pointers
越有用的reference to void
, or void *
,是对不完整类型的引用,但本身定义良好,然后是完整类型,具有大小,并且可以用作任何其他标准变量,如中所述ISO/IEC 9899:2017,§6.2.5 类型:
-
指向 void 的指针应具有与指向字符类型的指针相同的表示和对齐要求。
类似地,指向兼容类型的限定或非限定版本的指针应具有相同的表示和对齐要求。
所有指向结构类型的指针应具有相同的表示和对齐要求。
所有指向联合类型的指针应具有相同的表示和对齐要求。
指向其他类型的指针不需要具有相同的表示或对齐要求。
投射到void
它可以用作cast使表达式无效,但允许完成任何副作用这样的表达。该概念在以下标准中进行了解释:ISO/IEC 9899:2017,§6.3 转换,§6.3.2.2 无效:
-
void 表达式(类型为 void 的表达式)的(不存在的)值不得以任何方式使用,并且隐式或显式转换(除 void 之外)不得应用于此类表达式。
如果任何其他类型的表达式被计算为 void 表达式,则其值或指示符将被丢弃。 (评估 void 表达式的副作用。)
铸造的实际例子void
它的用途是防止函数定义中未使用的参数发出警告:
int fn(int a, int b)
{
(void)b; //This will flag the parameter b as used
... //Your code is here
return 0;
}
上面的代码片段显示了用于消除编译器警告的标准做法。演员阵容void
参数的b
充当不生成代码和标记的有效表达式b
用于防止编译器抱怨。
void
功能
这段落§6.3.2.2 无效该标准,还包括一些解释void
函数,即不返回表达式中可用的任何值的函数,但无论如何都会调用函数来实现副作用。
void
指针属性
正如我们之前所说,指向void
更有用,因为它们允许以通用方式处理对象引用,因为它们的属性在ISO/IEC 9899:2017,§6.3.2.3 指针:
-
指向 void 的指针可以与指向任何对象类型的指针相互转换。
指向任何对象类型的指针都可以转换为指向 void 的指针,然后再转换回来;结果应等于原始指针.
作为实际示例,想象一个函数根据输入参数返回指向不同对象的指针:
enum
{
FAMILY, //Software family as integer
VERSION, //Software version as float
NAME //Software release name as char string
} eRelease;
void *GetSoftwareInfo(eRelease par)
{
static const int iFamily = 1;
static const float fVersion = 2.0;
static const *char szName = "Rel2 Toaster";
switch(par)
{
case FAMILY:
return &iFamily;
case VERSION:
return &fVersion;
case NAME:
return szName;
}
return NULL;
}
在此代码片段中,您可以返回一个依赖于输入的通用指针par
value.
void
作为函数参数
指某东西的用途void
函数定义中的参数是在所谓的 ANSI 标准之后引入的,以有效区分具有可变参数数量的函数和具有以下参数的函数:没有参数.
从标准ISO/IEC 9899:2017, 6.7.6.3 函数声明符(包括原型):
- 类型的未命名参数的特殊情况
void
因为列表中唯一的项目指定该函数没有参数。
实际编译器仍然支持带有空括号的函数声明以实现向后兼容性,但这是一个过时的功能,最终将在未来版本的标准中删除。看未来方向 - §6.11.6 函数声明符:
- 使用带有空括号的函数声明符(不是原型格式参数类型声明符)是一种过时的行为
特征。
考虑以下示例:
int foo(); //prototype of variable arguments function (backward compatibility)
int bar(void); //prototype of no arguments function
int a = foo(2); //Allowed
int b = foo(); //Allowed
int c = bar(); //Allowed
int d = bar(1); //Error!
现在类似于您的测试,如果我们调用该函数bar
如下:
int a = 1;
bar((void)a);
触发错误,因为转换为void
对象不会将其置空。所以你仍在尝试通过void
对象作为没有任何函数的参数。
副作用
根据要求,这是一个简短的解释副作用概念。
副作用是指从语句执行中派生的对象和值的任何更改,这不是直接预期的效果。
int a = 0;
(void)b = ++a;
在上面的代码片段中,void 表达式失去了直接效果,赋值b
,但作为副作用增加的价值a
.
标准中唯一解释含义的参考文献可以在5.1.2.3 程序执行:
-
访问易失性对象、修改对象、修改对象
文件,或调用执行任何这些操作的函数都是
副作用,即执行状态的变化
环境。
表达式的求值一般包括两个值
副作用的计算和启动.