为什么当我取消引用 void 指针时需要进行强制转换?
我有这个例子:
int x;
void* px = &x;
*px = 9;
你能证明为什么这不起作用吗?
最佳答案
根据定义,void
指针指向一个“我不确定对象类型”。
根据定义,当您使用一元 *
运算符访问指针指向的对象时,您必须知道(当然,编译器必须知道)该对象的类型是什么。
所以我们刚刚证明了我们不能直接使用 *
取消引用 void
指针;我们必须始终首先将 void
指针显式转换为某个实际的对象指针类型。
现在,在许多人的心目中,“‘通用’指针应该指向什么类型?”的“显而易见”的答案。是“char
”。而且,曾几何时,在 void
类型被发明之前,字符指针通常被用作“通用”指针。因此,一些编译器(尤其是 gcc)对一些功能进行了扩展,让您可以使用 void
指针执行比标准要求更多的操作(例如指针算术)。
这样可能解释了您问题中的代码如何“工作”。 (不过,在您的情况下,由于指向的类型实际上是 int
,而不是 char
,如果它“有效”,那只是因为您使用的是小端字节序机。)
...话虽如此,我发现您问题中的代码不对我有用,甚至在 gcc 下也不行。它首先给我一个非致命警告:
warning: dereferencing ‘void *’ pointer
但随后它改变了主意并认为这是一个错误:
error: invalid use of void expression
我尝试过的第二个编译器说了类似的话:
<小时/>error: incomplete type 'void' is not assignable
附录:更多地说明为什么在取消引用指针时需要指向类型:
当您使用*
访问指针时,编译器将发出代码以从(或可能存储到)指向的位置获取。但是编译器必须发出访问一定数量字节的代码,并且在许多情况下,如何解释这些字节可能很重要。字节的数量和解释都由类型决定(这就是类型的用途),这正是需要实际的非 void 类型的原因。
据我所知,理解这一要求的最好方法之一就是考虑这样的代码
*p + 1
或者,甚至更好
*p += 1
如果p
指向char
,编译器可能会发出某种addb
(“添加字节”)指令。
如果p
指向int
,编译器将发出普通的add
指令。
如果p
指向float
或double
,编译器将发出浮点加法指令。等等。
但是如果p
是一个void *
,编译器不知道该怎么做。它提示(以错误消息的形式)不仅仅是因为 C 标准规定不能取消引用 void
指针,更重要的是,因为编译器根本不知道如何处理你的代码。
关于当您取消引用空指针时,您能证明为什么强制转换很重要吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58456940/