C语言void指针的用法

在使用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 failed\n");
}

3. 私有数据关联

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

#define DEVICE_NUM    10

struct 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*加以利用,能起到简化代码、减小耦合等作用。

猜你喜欢

转载自blog.csdn.net/qq_27575841/article/details/109731252