void* 是 C++ 中唯一能接收任意对象地址但不可直接解引用的指针类型,因缺乏类型信息而需强制转换为具体类型后才能访问;常用于 malloc/free、qsort 等泛型场景,但易引发未定义行为。
void* 是 C++ 中唯一能接收任意对象地址的指针类型,但它不携带类型信息。编译器禁止对 void* 直接使用 * 或 ->,因为不知道该读几个字节、怎么解释那块内存。
常见错误现象:
void* p = &x; int y = *p; // 错误:invalid use of 'void*' in arithmetic or indirection
必须先强制转回具体类型指针才能访问:
static_cast(推荐):类型安全,编译期检查(int*)p 或 reinterpret_cast:绕过类型检查,容易出错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
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
std::sort + lambda,避免 void* 手动转换reinterpret_cast 是唯一能将任意指针 ↔ void* 互转的 C++ cast(除 C 风格外),但它不保证可移植——特别是涉及指针大小、对齐、别名规则时。
典型高危操作:
double d = 3.14; void* p = &d; int i = *static_cast(p); // 未定义行为:读 取 double 内存为 int
真正安全的场景极少,仅限:
void*,之后严格转回原类型LPARAM、POSIX 线程参数)复杂点在于:一旦类型信息丢失,编译器无法帮你验证后续转换是否合理。它不会报错,但运行时可能崩溃或产生随机值。