当您取消引用空指针时,您能证明为什么强制转换很重要吗?

标签 c pointers casting void

为什么当我取消引用 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指向floatdouble,编译器将发出浮点加法指令。等等。

但是如果p是一个void *,编译器不知道该怎么做。它提示(以错误消息的形式)不仅仅是因为 C 标准规定不能取消引用 void 指针,更重要的是,因为编译器根本不知道如何处理你的代码。

关于当您取消引用空指针时,您能证明为什么强制转换很重要吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58456940/

相关文章:

c - 协议(protocol)消息反序列化不当

c - 为什么下面的代码会显示一个空白链表?

c - 使用函数将角度从度数转换为 C 中的弧度

c - 无法从函数获取字符串并在不重复 strcpy 和 strcat 命令的情况下显示

java - android.support.v7.widget.AppCompatTextView 无法转换为 android.widget.RelativeLayout

c - GCC Makefile 定义

c++ - 使用 const_cast 添加 const-ness - 坏主意?

python - 如何在 Cython 中使用内联函数

c++ - 将 int* 转换为字符串,然后将字符串转换为 int*

c++ - 在 C++ 中将结构类型转换为整数,反之亦然