首页 > 解决方案 > 为什么我们不能在非指针上使用 *?

问题描述

假设我有代码:

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

解决方案


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

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

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

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

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

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

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

因此,您不能隐含地将整数视为指针,即使您明确地这样做——也就是说,使用强制转换,如 in *((int *)y) = 3,您可能仍然处于不稳定的状态,尤其是在整数和指针不这样做的情况下t 在您的机器上具有相同的尺寸。

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


推荐阅读