首页 > 编程知识 正文

C语言void指针,指向void的指针

时间:2023-05-04 01:33:07 阅读:238983 作者:3068

在使用C语言进行开发的过程中,经常会遇到void*这样一个特殊的指针,容易被新手忽视,实际上void*非常强大。下面举几个比较常见的例子。

1. 用作泛型,接收任意数据类型指针

void*用于指向特定地址,而无需关心这个地址上存放着什么类型的数据。例如常见的memcpy等函数就用到void*,函数原型如下:

void *memcpy(void *des, void *src, size_t n)

此处的void *des和void *src可以接收任意类型的数据类型指针,既然是内存拷贝,入参就不应该限制传入什么类型的指针,逻辑上十分合理。

2. 动态内存申请与释放

动态内存申请函数返回值一般都是void*,如果申请成功则返回的是申请的内存块的首地址,申请失败则返回一个空指针NULL,NULL相当于(void *)0。C库的malloc函数原型如下:

void *malloc(size_t size)

一般申请完内存之后会与指针类型强制转换一起使用,如下所示。

typedef struct { char *name; int age; ...}animal, *animal_t;animal_t dog = (animal_t )malloc(sizeof(animal));if(!dog){ printf("malloc failedn");} 3. 私有数据关联

利用void*关联私有数据是一种常见的编程技巧,这种技巧在Linux中广泛存在。以下截取了xsdds老师的《Linux设备驱动开发详解》的一小段代码,保留了核心部分。struct file结构体中有一个void* private_data,在globalmem_open中使用struct file的private_data指针记录对应的设备的地址,那么后续只要获取到了file结构体指针,也就可以通过file结构体指针的private_data成员来间接获取到对应的设备了,例如globalmem_read函数。

#define DEVICE_NUM 10struct globalmem_dev{ struct cdev cdev; ...};struct globalmem_dev *global_devp;static int __init globalmem_init(void){ int i; /* 分配设备号等操作 */ ... /* 为global_devp申请DEVICE_NUM个globalmem_dev内存大小的空间 */ global_devp = kzalloc(sizeof(struct globalmem_dev) * DEVICE_NUM, GFP_KERNEL); if(!global_devp ) return -1; for(i = 0; i < DEVICE_NUM; i++) { /* 将申请的DEVICE_NUM个设备添加到字符设备节点中 */ globalmem_setup_cdev(global_devp + i, i); } return 0;}static int globalmem_open(struct inode *inode,struct file *filp){ /* 在globalmem_setup_cdev中已经添加到字符设备节点了 */ struct globalmem_dev *dev = container_of(inode->i_dedv, struct globalmem_dev, cdev); filp->private_data = dev;}static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos){ struct globalmem_dev *dev = filp->private_data;}

不仅仅是Linux,在一些RTOS中也常常能见到void*的身影,例如线程或定时器在创建时,往往需要一个入口函数或超时回调函数,而这些函数的入参往往就是一个void*,必要时对这些void*加以利用,能起到简化代码、减小耦合等作用。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。