为什么 void * 可以做通用指针

本文深入探讨了在void*出现前char*作为通用指针的角色,解析了char*和void*作为通用指针的原理,包括等大小转换、内存首地址保存及重新转换的特性,同时介绍了ANSIC标准下指针赋值的约束条件。

首先,说一下 void * 出现之前的解决方案:char * 在 void 类型出来之前充当通用指针的角色,但是 ASCII 指定了 void 关键字,则对于通用指针,void * 代替了 char *,但是仍然可以使用 char * 理解 void * 。

然后,从  char * 角度来分析,因为 char 是计算机中最基本的内存单元(8 bit),故任何其他类型都是 char 的整数倍,所以任何类型的指针赋值给 char * 后都会被正确地截断为原类型的内存首地址,并且重新解释不会给原数据类型带来错误。

进而得出核心的原理:

(1)在原指针对象的生命周期内, 将其转换成 char * 属于等大小转换,也就是说,任何指针的大小都是相等的。

(2)char *  保存的是原对象的内存首地址,这值与原指针对象保存的值相等。

(3)在原指针对象的生命周期内,将转换得到的 char * 重新转换成原来的指针对象,仍然会是最初的样子。

最终得出结论:char * 可以做通用指针, void * 可以做通用指针。

 

tips:针对指针,ANSI C标准明确了它的赋值约束条件(包括初始化):

1. 两个操作数都是指向有限定符或者无限度符的相容的指针;

2. 作操作数的指针所指向的类型必须具有右操作数指针所指向类型的全部限定符(左操作数的限定符可以更多)。

<think> 我们在讨论void*指针转换为T*指针的问题。根据引用[1]和[2],void*指针是一种通用指针,可以指向任何类型的数据,但具体类型未知。因此,我们可以将void*指针转换为特定类型的指针(T*),但需要显式类型转换。 引用[1]指出:“void* 可以指向任何类型的指针,但是带类型的指针不能指向void* 指针”,这里可能是指我们不能直接将void*赋值给特定类型的指针而不进行类型转换。实际上,在C语言中,将void*赋值给其他类型的指针需要显式转换(在C++中更是强制要求)。 引用[2]进一步说明,由于void*指针不知道所指向对象的类型,因此不能直接操作,需要转换为具体类型后才能进行操作。 另外,引用[3]提到了void*指针进行算术运算的问题,但这不是当前问题的重点,但需要注意转换后进行操作。 因此,结论是:void*指针可以转换为T*指针,但必须进行显式类型转换。 例如: ```c int a = 10; void *vp = &a; // void*指向int int *ip = (int *)vp; // 显式转换为int* ``` 在C++中,我们通常使用static_cast进行转换: ```cpp int *ip = static_cast<int*>(vp); ``` 注意:转换时必须确保void*指针确实指向一个T类型的对象,否则会导致未定义行为。 §§相关问题§§ 1. 在C语言中,将void*指针转换为具体类型指针时需要注意什么? 2. 为什么在C++中推荐使用static_cast进行void*的转换而不是C风格的转换? 3. 如何安全地进行void*指针的转换以避免未定义行为? </think>根据提供的引用内容,void*指针可以转换为T*(特定类型)指针,但需要注意以下关键点: ### 1. **转换可行性** void*指针可以安全地转换为任何具体类型的指针(T*),但**必须显式进行类型转换**。如引用[1]所述: > "void* 可以指向任何类型的指针" > 但"带类型的指针不能指向void* 指针"(即不能隐式转换)[^1] 这意味着您需要显式类型转换: ```c void* void_ptr = ...; // 某个内存地址 T* t_ptr = (T*)void_ptr; // 显式转换为T*类型 ``` ### 2. **操作限制** 转换前void*指针**不能直接操作数据**(引用[2]): > "不能直接操作void*指针所指的对象,因为不知道这个对象到底是什么类型" [^2] > 必须先转换为具体类型指针才能安全访问数据: ```c void* data = malloc(sizeof(int)); // 分配内存 *(int*)data = 42; // 转换为int*后操作 ``` ### 3. **算术运算限制** void*指针**不支持直接算术运算**(引用[3]): > "void * 指针与整数进行加减运算...不符合标准C语言规范" > 需先转换为具体类型指针(如`char*`): ```c void* ptr = ...; // 错误:ptr += offset; char* c_ptr = (char*)ptr + offset; // 正确法 ``` ### 4. **类型安全风险** 转换时必须**确保实际类型匹配**: - 若void*实际指向类型`A`,却强制转换为`B*`,会导致未定义行为 - 在C++中建议用`static_cast<T*>(void_ptr)`增强安全性 --- ### 总结 | 操作 | 是否允许 | 条件/方法 | |---------------|---------------|------------------------------| | void* → T* | ✅ 允许 | 显式类型转换 `(T*)void_ptr` | | 直接操作数据 | ❌ 禁止 | 需先转为具体类型指针 | | 算术运算 | ❌ 禁止 | 需先转为`char*`等有大小类型 | | 隐式转换 | ❌ 禁止 | 必须显式转换 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

东风吹柳

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

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

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

打赏作者

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

抵扣说明:

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

余额充值