这是一个非常基础且核心的概念,理解它对于学习 C 语言至关重要,我们将从几个层面来拆解它:

- 分解
void foo void关键字在函数中的三种角色- 一个完整的示例
void foo()与void foo(void)的区别- *
void指针 (`void `)**
分解 void foo
void foo 这个表达式本身不是一个完整的 C 语句,但它描述了一个函数的原型或声明的核心部分,我们可以把它分解成两个关键部分:
void: 这是一个 C 语言的关键字,意思是“无类型”、“空”或“不返回任何值”,它用在函数名之前,表示这个函数不返回任何值。foo: 这是函数的名称,你可以给它取任何合法的标识符名称,calculate_sum,print_message,process_data等。foo是一个非常常见的占位符名称,常用于教学示例。
void foo 的字面意思是:“一个名为 foo 的函数,它不返回任何值”。
void 关键字在函数中的三种角色
void 在函数的使用中扮演着三个不同的角色,这也是初学者容易混淆的地方。
角色 A: 作为函数的返回类型 (用在函数名前)
这是 void foo 中 void 的作用。

- 含义: 函数执行完毕后,不向调用者返回任何数据。
- 类比: 你让一个员工去完成一项任务,把垃圾倒了”,他完成这个任务后,不需要向你报告任何结果(比如垃圾的重量、颜色等),他只是执行了“倒垃圾”这个动作。
- 语法:
void my_function() { // 函数体 // 这里可以执行操作,但不能使用 return 来返回一个值 // return 10; // 这是错误的! } - 调用方式: 直接调用函数名即可。
my_function(); // 调用函数,不接收任何返回值 // int result = my_function(); // 错误!不能接收一个不存在的返回值
角色 B: 作为函数的参数列表 (用在括号里)
当 void 用在函数的括号 内时,它表示这个函数不接受任何参数。
- 含义: 函数被调用时,不能向它传递任何数据。
- 类比: 你让一个员工去执行一项任务,并且这项任务不需要任何外部信息,原地跳一下”,你不需要告诉他跳多高、跳多远。
- 语法:
void my_function(void) { // 括号里的 void 表示无参数 // 函数体 } - 调用方式: 调用时也不能传递任何参数。
my_function(); // 正确 // my_function(10); // 错误!函数不接受参数
重要提示: 在 C 语言中,
void my_function()和void my_function(void)是有区别的(详见下一节),但为了清晰表示“无参数”,强烈推荐使用void my_function(void)的形式。
角色 C: 作为通用的指针类型 (void *)
这是 void 的第三个重要角色,它是一个特殊的指针类型。
-
含义:
void *指向一个未知类型的内存地址,它是一个“通用指针”或“万能指针”,可以指向任何类型的数据。
(图片来源网络,侵删) -
限制: 你不能直接解引用(即通过 操作符获取其指向的值)一个
void *指针,因为编译器不知道这个内存里存放的是什么类型的数据(是int?char?还是struct?)。 -
用途: 主要用于函数参数,允许函数接收任意类型的指针,C 标准库中的
memcpy函数就使用了void *。 -
语法:
void *ptr; // 声明一个 void 指针 int a = 10; char c = 'A'; ptr = &a; // void 指针可以指向 int ptr = &c; // 也可以指向 char // 要使用它,必须先进行强制类型转换 int *int_ptr = (int *)ptr; printf("Value: %d\n", *int_ptr); // 现在可以安全地解引用了
一个完整的示例
下面是一个完整的、可运行的 C 程序,展示了 void 作为返回类型和参数类型的用法。
#include <stdio.h>
// 1. 函数声明 (原型)
// - 返回类型: void (不返回值)
// - 参数类型: void (不接受参数)
void print_welcome_message(void);
// 2. 另一个函数声明
// - 返回类型: void
// - 参数类型: int (接受一个整数参数)
void print_number_times(int times);
// 3. main 函数
// - 返回类型: int (向操作系统返回一个状态码)
// - 参数类型: int argc, char *argv[] (接受命令行参数)
int main(void) {
printf("--- Program Start ---\n");
// 调用无参数的函数
print_welcome_message();
// 调用一个带参数的函数
int repeat_count = 3;
print_number_times(repeat_count);
printf("--- Program End ---\n");
// main 函数返回 0,表示程序成功执行完毕
return 0;
}
// 4. 函数定义
void print_welcome_message(void) {
printf("Hello, C World!\n");
printf("This function takes no arguments and returns nothing.\n");
}
void print_number_times(int times) {
printf("The number %d will be printed %d times.\n", times, times);
for (int i = 0; i < times; i++) {
printf("Count: %d\n", i + 1);
}
}
输出结果:
--- Program Start ---
Hello, C World!
This function takes no arguments and returns nothing.
The number 3 will be printed 3 times.
Count: 1
Count: 2
Count: 3
--- Program End ---
void foo() 与 void foo(void) 的区别
这是一个在 C 语言中非常重要且容易出错的细节。
-
void foo(void): 这是现代、明确、推荐的写法。- 它明确地告诉编译器和程序员:“这个函数不接受任何参数。”
- 如果尝试调用
foo(10),编译器会立即报错。
-
void foo(): 这是 C 语言从 C 继承来的旧式写法,被称为“未指定参数列表”。- 在 C 语言中,这种写法意味着:“这个函数可以接受任意数量的参数,就像
printf那样。” - 在 C++ 中,
void foo()和void foo(void)的含义是完全相同的,都表示不接受参数。 - 在 C 语言中,如果你声明
void foo()并尝试调用foo(10),编译器可能不会报错(取决于编译器的严格程度),这会导致未定义行为,是程序中非常隐蔽的 bug。
- 在 C 语言中,这种写法意味着:“这个函数可以接受任意数量的参数,就像
为了写出清晰、健壮、可移植的 C 代码,当你想定义一个无参数的函数时,始终使用 void foo(void) 的形式。
| 用法位置 | 含义 | 示例 |
|---|---|---|
| 函数名前 | 函数不返回任何值 | void my_func(); |
| 函数括号内 | 函数不接受任何参数 (推荐写法) | void my_func(void); |
| 作为指针类型 | 通用指针,可指向任意类型,使用前需转换 | void *ptr = &some_variable; |
理解 void 的这三种用法是掌握 C 语言函数和指针的关键一步。void 的核心思想就是“无”或“通用”,并根据它在代码中的位置来判断其具体含义。
