void 类型指针以及指针数组

本文详细介绍了C++中void类型的特殊性质及其与void*指针的交互方式,包括如何将不同类型的指针转换为void*型,如何使用void*型数组替代多个参数,以及在使用时应注意的问题。通过实例演示了如何正确地进行类型转换和避免常见的陷阱,旨在帮助开发者更好地理解和利用void类型和void*指针在实际编程中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

void 类型比较特殊,它可以表示所有的类型,但是又不能像其他类型那样声明成实体。在很多项目中的函数的参数使用void* 型数组,在void*数组中,即可以有int型,可以有char型,也可以有结构体,将这些参数放在一个void* 型数组中。
值得注意的是,不能直接使用void型变量,而是使用void*,即void 型的指针。
比如:

int a;
void b;
void* c;

这里第一行声明是正确的,第二行声明是错误的,第三行是正确的。
void指针变量的正确用法为:
1.将int型转换成void*型:

      void *c = NULL;
      int a = 10;
      c = (int*)&a;
      std::cout<<(*(int*)c);
这里有很多人会犯这样的错误 : ‘void*’不是一个指向对象的类型,代码如下
           void *c = NULL;
           int a = 10;
           c = (int*)&a;
           std::cout<<(*c)<<endl;

这里可以有人认为c = (int*)&a;这里已经将c的类型强制转换成了int*型,事实上是没有的,还需要在使用的时候进行强制转换。

2.将char* 转换成void*型:

1. char* 开辟数组
       void *c = NULL;
       char *a = NULL;
       a = (char*)malloc(sizeof(char)*10);
       char *b = a;
       for(int i =0;i < 5;i++){
          *(b++) = i+'a';
       }
        *b = '\0';
       c = (char*)a;
       cout<<(char*)c;
       /***输出结果: abcde***/


2. void* 开辟数组
       void *c = NULL;
       char *a = NULL;
       c = (char*)malloc(sizeof(char)*10);
       a = (char*) c;
       for(int i =0;i < 5;i++){
          *(a++) = i+'a';
       }
        *a = '\0';
        cout<<(char*)c;
      /***输出结果: abcde***/

这两种方法本质是一样的,个人喜好而已。

void* 类型的数组使用

  比如说我在一个函数中需要使用int型参数一个,char型参数一个,char*型参数一个,而我又不想使参数列表太长,所以我决定使用void*数组替代以上三个参数。
     void* arg[3];    //声明一个void*型数组

     int a = 10;
     char b = 'b';
     char *c = NULL;      //原来的参数是 a ,b ,c
     arg[0] = (int*)&a;
     arg[1] = (char*)&b;

     arg[2] = malloc(sizeof(char)*10);
     c = (char*)arg[2];
     for(int i = 0; i < 5;i++){
         *(c++) = i+'a';
     }
     *c = '\0';

      //转换后的参数为arg 是一个void*型的数组,在使用时也需要按照对应的类型进行强制转换
     cout<<*(int*)arg[0]<<'\n';
     cout<<*(char*)arg[1]<<'\n';
     cout<<(char*)arg[2]<<'\n';

    /***输出: 
    10
    b
    abcde
    ***/
 void* 数组虽然可以使函数的参数个数变少,但是缺点也是显而易见的,当你在函数的参数列表中看到一个void*数组时,你是不知道它究竟代表什么意思,所以在使用void*型数组传参时一定要写好注释,利人利己。以上是我的个人经验,其他的利弊还没有深入探究。

//以下内容参考: http://www.cnblogs.com/CoolSummer/p/3205679.html

这里附上的总结:
1.void类型表示无类型,也可以看成是任意类型。
比如: void* c = (int )a; void c = (char *)a;等等

2.可以使用任意类型的指针为void型指针赋值,但是不能用void型指针为已知类型的指针赋值。
void* c = (int *)a; 正确
int b = (void)d; 错误

3.函数的参数使用void型指针,表示可以传入任意类型的参数。
int add(void* a, void* b);
所以当你看到这样一个参数列表时,根本不知的a,b 的具体类型(int or unsigned int 等等)。

4.void可以看成是一种抽象类型,想想virtual,虚函数、虚基类,他们都是抽象的,是虚的。所以不能实例化一个虚的东西,也就是说不能声明一个void型的变量(注意这里我说的是变量,不是指针)。可以想象成void类型是所有已知类型之上的一个抽象类型。
所以在使用malloc时一般都会在前面加上一个指针类型进行强制转换。

5.既然void类型是抽象的,那么就不能对它进行具体的算数运算,例如void * pvoid; pvoid++; pvoid +=2;都是invalid,指针的++操作是给当前分配的内存空间增大一个单元的空间,可是void类型你都不知道它要存啥,你当然不知道他一个单元要多大,所以就不能做算术运算。

### 关于指向 `void` 类型指针数组指针 在C/C++编程语言中,`void*` 是一种特殊类型指针,它可以存储任何数据类型的地址。然而,由于 `void*` 不携带类型信息,在对其进行解引用或算术运算之前通常需要将其转换为目标类型指针。 当涉及到指向 `void` 类型指针数组指针时,这意味着有一个指针变量可以访问一组 `void*` 类型的元素。这种结构允许创建一个通用的数据容器来保存不同类型对象的地址[^1]。 #### 定义与初始化 定义并初始化一个指向 `void` 指针数组指针可以通过如下方式实现: ```c++ #include <iostream> int main() { // 创建不同类型的变量 int integer = 42; double floatingPoint = 3.14; // 声明两个 void* 类型指针用于存储上述变量的地址 void* array_of_void_ptrs[2]; array_of_void_ptrs[0] = static_cast<void*>(&integer); array_of_void_ptrs[1] = static_cast<void*>(&floatingPoint); // 声明指向该 void* 数组指针 void** ptr_to_array = array_of_void_ptrs; std::cout << "Value at index 0 (as int): " << *static_cast<int*>(ptr_to_array[0]) << "\n"; std::cout << "Value at index 1 (as double): " << *static_cast<double*>(ptr_to_array[1]); return 0; } ``` 这段代码展示了如何声明和使用指向 `void` 类型指针数组指针。注意这里使用了静态强制转换 (`static_cast`) 来确保安全地将 `void*` 转换回原始类型以便读取其值。 #### 使用场景 这类指针主要用于以下几个方面: - 实现泛型函数库中的参数传递机制; - 构建能够容纳多种基本类型或其他复杂结构体的对象池; - 设计回调接口时作为用户自定义上下文数据的载体; 通过这种方式可以在一定程度上提高程序灵活性的同时保持良好的性能特性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chomol

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值