为什么我们不能在非指针上使用*?

假设我有代码:

int x = 5;
int* p = &x;

然后写入*p将返回 5 并允许我修改x(如预期的那样)。说,无论出于何种原因,我然后写:

int y = p;      // y holds x's address 
*y = 3;         // this is invalid and throws an error when compiling
*((int*)y) = 3; // this is okay

(在 gcc 9.2 上编译时)

我的问题是:为什么 C 不允许我们*在非指针类型上使用?

回答

C 是一种强类型语言,这意味着允许对对象进行的操作(以及这些操作的解释)是对象类型的函数。这就是对象具有类型的字面意思:类型决定了您可以对对象执行的操作。

一元*(指针间接运算符)是为指针类型定义的,而不是为整数类型定义的。

如果您想将整数的值视为指针,则可以使用显式转换,如*((int *)y) = 3;您在问题中提到的示例。

没有为整数定义一元运算*符有两个原因:

  1. 取一个整数并假装它是一个指针通常是一个坏主意,不值得鼓励。如果您真的想这样做,那么强加给您的额外成本——即您必须使用该指针强制转换——是合适的。

  2. 裸表达式*y不包含足够的信息来知道指向的对象可能有多大。如果您编写*y = 3并且它合法的,那么编译器如何知道分配 an int、 ashort或 a char

第 2 点是关键。重要的是要记住 C 没有一种“指针”类型。每个指针类型都包含指针将指向的对象类型的规范。这不是偶然的,它是基本的,而且没有办法绕过它。

所以你不能隐式地把一个整数当作一个指针来对待,即使你明确地这样做——也就是说,用一个强制转换,就像在 中一样*((int *)y) = 3,你可能仍然处于不稳定的状态,特别是如果整数和指针不这样做'你的机器上有相同的尺寸。

如今,这通常是一个糟糕的主意,以至于编译器正在慢慢放弃他们旧的“程序员必须知道他在做什么”的态度,并且对警告变得有些嘶嘶声。例如,int y = p通常会给你一个关于指向 int 的指针赋值的警告,即使使用显式转换,*((int *)y) = 3也可能会给你一个关于“从不同大小的整数转换为指针”的警告。


以上是为什么我们不能在非指针上使用*?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>