c++中的void指针

基本含义

void*在The C++ Programming Language中解释为:pointer to an object of unknown type. 即指向一未知类型的对象。

那么我们什么时候会用到或者见到void*指针呢?
在一些底层的代码中,我们可能需要处理一片内存,但是我们并不知道这一块内存存储的到底是什么类型的对象,在之后的例子中将会以memset讲解。

使用规则

  1. void*可以被赋值为任意类型对象的指针(隐式转化),除了指向函数或者成员的指针
  2. void*可以被另一个void*赋值
  3. void*之间可以比较是否相等
  4. void*可以被显式转化为其他类型
  5. 除以上的4点操作之外的其他操作都是不安全的

例1

代码引用自The C++ Programming Language

void f(int *p) {
        void* pi = p;  //implicit conversion from int* to void*   
        *pv;  //error: can't redeference void*        
        ++pv;  //error: can't increment void* (the size of the object pointed to is unknown)

        int* pi2 = static_cast<void*>(pi);  //explicit conversion back to int*

        double* pd1 = pv;  //error
        double* pd2 = pi;  //error: the type of the pointers is not equal
        double* pd3 = static_cast<void*>(pi);  //unsafe
}

例2

memset的原型为:void * memset ( void * ptr, int value, size_t num );
其中第一个参数为void*,因为我们并不知道要memset的到底是一个int数组,还是char型数组之类的,所以我们用void*来代表第一个参数,在C标准库一书中,memset的实现如下:

void* memset(void* ptr, int value, size_t num) {
    const unsigned char uc = value;    //convert int to unsigned char
    unsigned char* p;    //void* will be implicit convert to unsigned char*
    for (p = ptr; num > 0; num--, p++) {
        *p = value;
    }
}

在函数内的第2行,我们声明一个unsigned char*类型的指针p,并在循环内,将其void*隐式转化为unsigned char*型。
但是该代码只能在gcc下编译通过,如果用g++的话,必须要进行显式类型转化,代码如下:

void* memset(void* ptr, int value, size_t num) {
    const unsigned char uc = value;
    unsigned char* p;
    for (p = static_cast<unsigned char*>(ptr); num > 0; num--, p++) {
        *p = value;
    }
}

以及通过上面的代码,我们不难看出为什么对int型数组进行内存初始化:memset(a, 1, sizeof(a))答案不对了= =

在 C/C++ 中,void 指针(`void*`)是一种特殊的指针类型,它可以指向任意类型的数据,具有多种具体用途: - **通用数据处理**:在编写通用函数时,由于函数可能需要处理不同类型的数据,使用 `void*` 可以提高函数的通用性。例如,`memcpy` 和 `memset` 函数的参数类型就是 `void*`,这样任何类型的指针都可以传入这两个函数中,体现了内存操作函数操作内存本身而不考虑内存类型的特点[^2]。 ```c #include <stdio.h> #include <string.h> int main() { int arr1[5] = {1, 2, 3, 4, 5}; int arr2[5]; // 使用 memcpy 复制 arr1 到 arr2 memcpy(arr2, arr1, sizeof(arr1)); for (int i = 0; i < 5; i++) { printf("%d ", arr2[i]); } printf("\n"); return 0; } ``` - **实现数据结构**:在实现一些通用的数据结构时,`void*` 可以用来存储任意类型的数据。例如,链表、栈、队列等数据结构可以使用 `void*` 来存储不同类型的元素,使得这些数据结构可以处理多种数据类型。 ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构 typedef struct Node { void* data; struct Node* next; } Node; // 创建新节点 Node* createNode(void* data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; return newNode; } int main() { int num = 10; Node* node = createNode(&num); int* value = (int*)node->data; printf("Value: %d\n", *value); free(node); return 0; } ``` - **函数返回任意类型指针**:函数可以返回 `void*` 类型的指针,这样函数可以根据不同的情况返回不同类型的指针。在使用返回的指针时,需要进行显式的类型转换。 ```c #include <stdio.h> // 函数返回 void* 指针 void* getPointer(int choice) { int num = 20; char ch = 'A'; if (choice == 1) { return &num; } else { return &ch; } } int main() { int* intPtr = (int*)getPointer(1); char* charPtr = (char*)getPointer(2); printf("Integer value: %d\n", *intPtr); printf("Character value: %c\n", *charPtr); return 0; } ``` - **类型转换**:在把 `void` 类型指针赋值给其他类型的指针时,必须使用类型强转。这种强制类型转换,在 C 中是可选的,但是在 C++ 中是必须的,因为两种语言都使用强制类型转换,要遵循 C++ 的要求[^3]。 ```c++ #include <iostream> int main() { int num = 30; void* p1 = &num; int* a1 = (int*)p1; std::cout << "Value: " << *a1 << std::endl; return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值