c语言中void *p,C语言陷阱与技巧31节,都说void*指针是“万能指针”,它万能在哪...

在C语言程序开发中,一些比较成熟的库函数常常会被使用。毕竟,如果手边就有不错的“轮子”可以用,没有程序员愿意再花费精力凭空造一个轮子出来。

9803b3c05c4b6f7abcd5bac41ba5b1c3.png没有程序员愿意凭空造轮子

奇怪的 void* 指针

事实上,C语言标准库提供了非常丰富的成熟函数供程序员使用,不过不知道读者注意到没,有些库函数的参数是 void * 类型的,例如:

void *memcpy(void *dest, constvoid *src, size_t n);void *memmove(void *dest, constvoid *src, size_t n);前面的章节在讨论C语言指针时,提到指针从某种程度上来说,无非就是一个地址,它的类型只是用于说明数据结构的。例如 int 型指针告诉编译器该地址处紧接着的 4 字节按照 int 型数据解释,double 型指针高速编译器接下来的 8 字节按照 double 型数据解释。

这里假定int型变量占用4字节内存空间,double 型变量占用 8 字节内存空间。

对于 void 型指针,之前的分析似乎就不再适用了。因为 void 类型是一个特殊的类型,常被称作“空类型”,C语言中没有 void 类型的变量,所以在遇到 void 指针时,编译器根本不知道如何解释接下来的内存,甚至编译器都不知道接下来多少内存属于它。

c40a27997da538395b10b4820f235471.png编译器都不知道接下来多少内存属于它

正因为如此,在C语言程序开发中,遇到 void * 指针时,如果需要访问它指向的内存,需要重新指定类型,否则就会报错。例如下面这段C语言代码:

#include void myprint(void *p){char c = p[0];printf("c=%c\n", c);}int main(){char buf[] = "hello world"; myprint(buf);return0;}void myprint(void *p){char c = ((char*)p)[0];printf("c=%c\n", c);}有时候为了简便,常常使用中间变量:

void myprint(void *p){char *cp = (char*)p;char c = cp[0];printf("c=%c\n", c);}这时再编译执行就一切正常了。

为什么使用 void * 指针

仅从上面的实例来看,使用 void 指针似乎比较麻烦:至少强制类型转换操作是少不了的。那为什么还要使用 void 指针呢?

785b0ce396c5823d6cc38bd1628dc31d.png为什么要是用void*指针

仔细分析上面的实例,读者应注意“在使用 void 型指针时,要将其先转换为 char 型”,这其实要求程序员事先了解 void 指针指向的数据结构(本例是 char 型),否则就没法使用 void * 指针。

利用这一点,程序员可以使用 void * 将不公开的数据隐藏起来,避免外界调用者访问和修改它。例如,在实际的C语言项目开发中,操作某个对象时,常常先构建结构体 struct S 描述该对象,然后使用 init() 函数获取相应信息,因为接下来的操作函数 handle() 需知道要操作哪个对象,所以要使用 init() 函数返回的信息,C语言代码似乎可以这么写:

struct S *p = init();handle(p);从上面两行C语言代码可以看出,其实外界调用可以不用关心 p 的具体数据结构。不过,如果这么写了,外界又的确可以随意访问 p 指向的数据结构,这样就很危险了。事实上,我们完全可以将 p 转换为 void * 指针:

void *p = init();handle(p);这样一来,只有 init() 库的开发者才能访问 p 指向的内容,避免外界调用者“意外”或者“恶意”的修改,整个C语言程序就会稳定和安全很多了。

另外,void 指针在一些教科书里被称作“万能指针”,这主要是因为任意指针都可以使用 void 指针传递,并且编译器不会报出“类型不匹配”相关的警告。例如,要是将 myprint() 函数的参数类型修改为 int * 型,相关C语言代码如下:

void myprint(int *p){char *cp = (char*)p;char c = cp[0];printf("c=%c\n", c);}int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);小结

本节抛砖引玉,主要讨论了 void 指针在实际C语言项目开发中的特性和用途。void 指针可以将不希望被公开的数据结构隐藏,避免外界调用“意外”或者“恶意”的修改。另外,void * 指针作为“万能指针”,可以传递任意类型的指针,而不引起“类型不匹配”相关的编译警告。

cdea385f054999f982fc9b88cce9a71e.png点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦

举报/反馈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值