c++ void*指针用法_c++万能指针类型转换

void* 是 C++ 中唯一能接收任意对象地址但不可直接解引用的指针类型,因缺乏类型信息而需强制转换为具体类型后才能访问;常用于 malloc/free、qsort 等泛型场景,但易引发未定义行为。

void\* 是什么,为什么不能直接解引用

void* 是 C++ 中唯一能接收任意对象地址的指针类型,但它不携带类型信息。编译器禁止对 void* 直接使用 *->,因为不知道该读几个字节、怎么解释那块内存。

常见错误现象:

void* p = &x;
int y = *p;  // 错误:invalid use of 'void*' in arithmetic or indirection

必须先强制转回具体类型指针才能访问:

  • static_cast(推荐):类型安全,编译期检查
  • 用 C 风格 (int*)preinterpret_cast:绕过类型检查,容易出错

malloc/free 场景下 void\* 的典型用法

C 标准库函数 malloc 返回 void*,C++ 中虽可隐式转为任意指针,但显式转换更清晰、兼容性更好(尤其跨平台或混用 C 头文件时)。

int* arr = static_cast(malloc(10 * sizeof(int)));
if (arr != nullptr) {
    arr[0] = 42;
    free(arr);  // 注意:free 只接受 void*
}

关键点:

  • free 参数是 void*,传 int* 没问题(自动转)
  • new/delete 不涉及 void*,它们自带类型信息,优先用 new int[10] 而非 malloc
  • 别对 new 出来的地址调用 free,或对 malloc 出来的地址调用 delete

函数参数中 void\* 用于泛型接口(如 qsort)

C 风格回调函数常靠 void* 实现“伪泛型”,例如 qsort 的比较函数签名是:int (*)(const void*, const void*)

写比较函数时必须手动转回原类型:

int compare_ints(const void* a, const void* b) {
    int ia = *static_cast(a);  // 注意 const 修饰要匹配
    int ib = *static_cast(b);
    return (ia > ib) - (ia < ib);
}
// 使用:
int data[] = {3, 1, 4};
qsort(data, 3, sizeof(int), compare_ints);

容易踩的坑:

  • 忘记加 const 导致编译失败(qsort 传入的是 const void*
  • 结构体比较时,只转指针不转成员访问方式,比如 static_cast(a)->field
  • C++ 中更推荐用 std::sort + lambda,避免 void* 手动转换

void\* 和 reinterpret_cast 的危险边界

reinterpret_cast 是唯一能将任意指针 ↔ void* 互转的 C++ cast(除 C 风格外),但它不保证可移植——特别是涉及指针大小、对齐、别名规则时。

典型高危操作:

double d = 3.14;
void* p = &d;
int i = *static_cast(p);  // 未定义行为:读取 double 内存为 int

真正安全的场景极少,仅限:

  • 把对象地址暂存为 void*,之后严格转回原类型
  • 与系统 API 交互(如 Windows LPARAM、POSIX 线程参数)
  • 实现内存池或自定义分配器时做原始内存管理

复杂点在于:一旦类型信息丢失,编译器无法帮你验证后续转换是否合理。它不会报错,但运行时可能崩溃或产生随机值。