void 关键字

本文详细解析了C/C++语言中的void关键字及其应用场景,包括void指针的特性与限制、void在函数声明中的作用以及如何正确使用void指针进行内存操作。

Void 关键字:

void 的字面意思是“空类型”,void *则为“空类型指针”,void *可以指向任何类型的数据。

众所周知,如果指针p1 和p2 的类型相同,那么我们可以直接在p1 和p2 间互相赋值;

如果p1 和p2 指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的

指针类型转换为左边指针的类型。

float *p1;

int *p2;

p1 = p2;

其中p1 = p2 语句会编译出错,必须改为:

p1 = (float *)p2;

而void *则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换:

void *p1;

int *p2;

p1 = p2;

但这并不意味着,void *也可以无需强制类型转换地赋给其它类型的指针。因为“空类型”可

以包容“有类型”,而“有类型”则不能包容“空类型”

void *p1;

int *p2;

p2 = p1;

这样就会出错。

void 修饰函数返回值和参数

如果函数没有返回值,一定要声明为void 类型。

如果函数无参数,那么应声明其参数为void

int function(void)//有返回值

{

       return 1;

}

像这种是不好的

fun()

{

       return 1;

}

警告:返回类型默认为 ‘int’

 

void 指针

不能对void 指针进行算法操作

如:

void * pvoid;

pvoid++; //ANSI:错误

pvoid += 1; //ANSI:错误

进行算法操作的指针必须是确定知道其指

向数据类型大小的。也就是说必须知道内存目的地址的确切值。

例如:

int *pint;

pint++; //ANSI:正确

但是大名鼎鼎的GNU(GNU's Not Unix 的递归缩写)则不这么认定,它指定void *的算法

操作与char *一致。因此下列语句在GNU 编译器中皆正确:

pvoid++; //GNU:正确

pvoid += 1; //GNU:正确

并提高程序的可移植性,我们可以这样编写

实现同样功能的代码:

void * pvoid;

(char *)pvoid++; //ANSI:正确;GNU:正确

(char *)pvoid += 1; //ANSI:错误;GNU:正确

典型的如内存操作函数memcpy 和memset 的函数原型分别为:

void * memcpy(void *dest, const void *src, size_t len);

void * memset ( void * buffer, int c, size_t num );

这样,任何类型的指针都可以传入memcpy 和memset 中,这也真实地体现了内存操作

函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型。如果memcpy

和memset 的参数类型不是void *,而是char *,那才叫真的奇怪了!这样的memcpy 和memset

明显不是一个“纯粹的,脱离低级趣味的”函数!

下面的代码执行正确:

例子:memset 接受任意类型指针

int IntArray_a[100];

memset (IntArray_a, 0, 100*sizeof(int) ); //将IntArray_a 清0

例子:memcpy 接受任意类型指针

int destIntArray_a[100], srcintarray_a[100];

//将srcintarray_a 拷贝给destIntArray_a

memcpy(destIntArray_a, srcintarray_a, 100*sizeof(int) );

有趣的是,memcpy 和memset 函数返回的也是void *类型,标准库函数的编写者都不是一

般人。

void 不能代表一个真实的变量。

因为定义变量时必须分配内存空间,定义void 类型变量,编译器到底分配多大的内存呢。

下面代码都企图让void 代表一个真实的变量,因此都是错误的代码:

void a; //错误

function(void a);//错误

void 体现了一种抽象,这个世界上的变量都是“有类型”的。

在C语言中,`void`关键字主要用于表示“无类型”或“无返回值”,其高级使用方法包括以下几种: 1. **函数返回类型**: - 当函数不需要返回值时,可以使用`void`作为返回类型。例如: ```c void printHello() { printf("Hello, World!\n"); } ``` 2. **函数参数**: - 当函数不需要参数时,可以使用`void`作为参数列表,以明确表示函数不接受任何参数。例如: ```c int getValue(void) { return 42; } ``` 3. **指针类型**: - `void*`是一种通用指针类型,可以指向任何类型的数据,但在解引用时需要先进行类型转换。例如: ```c void* ptr; int num = 10; ptr = &num; printf("%d", *(int*)ptr); // 需要强制类型转换 ``` 4. **函数指针**: - 可以使用`void`来定义函数指针,表示该函数指针可以指向任何返回类型为`void`的函数。例如: ```c typedef void (*FuncPtr)(void); void myFunction() { printf("This is my function.\n"); } FuncPtr func = myFunction; func(); // 调用函数 ``` 5. **动态内存分配**: - `malloc`和`calloc`等函数返回`void*`,可以分配任意类型的内存。例如: ```c int* arr = (int*)malloc(10 * sizeof(int)); free(arr); // 记得释放内存 ``` 6. **回调函数**: - 在事件驱动编程或回调机制中,`void`函数常被用作回调函数。例如: ```c void callback() { printf("Callback executed.\n"); } void registerCallback(void (*cb)(void)) { cb(); // 调用回调函数 } registerCallback(callback); ``` 7. **类型安全**: - 使用`void*`时需要注意类型安全,避免错误的类型转换导致未定义行为。 8. **可变参数函数**: - 在定义可变参数函数时,可以使用`void`来确保函数没有固定参数。例如: ```c #include <stdarg.h> void logMessage(const char* format, ...) { va_list args; va_start(args, format); vprintf(format, args); va_end(args); } ``` ### 总结 `void`关键字在C语言中非常灵活,可以用于函数返回类型、参数列表、指针类型、函数指针、动态内存分配、回调函数等场景。正确使用`void`可以提高代码的灵活性和可读性,但同时也需要注意类型安全和内存管理的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值