c - 为什么我们不能在非指针上使用 *?
问题描述
假设我有代码:
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;
您在问题中提到的示例所示。
没有为整数定义一元运算*
符有两个原因:
取一个整数并假装它是一个指针通常是一个坏主意,而不是值得鼓励的事情。如果您真的想这样做,那么强加给您的额外成本(即您必须使用该指针转换)是合适的。
裸表达式
*y
不包含足够的信息来了解指向的对象可能有多大。如果您编写*y = 3
并且它是合法的,编译器如何知道分配 aint
、 ashort
或 achar
?
第2点是关键。重要的是要记住 C 没有一种“指针”类型。每个指针类型都包含指针将指向的对象类型的规范。这不是偶然的,它是根本的,没有办法绕过它。
因此,您不能隐含地将整数视为指针,即使您明确地这样做——也就是说,使用强制转换,如 in *((int *)y) = 3
,您可能仍然处于不稳定的状态,尤其是在整数和指针不这样做的情况下t 在您的机器上具有相同的尺寸。
这些天来,这通常是一个糟糕的主意,编译器正在慢慢放弃他们旧的“程序员必须知道他在做什么”的态度,并且对警告变得有些嘶哑。例如,int y = p
通常会给您一个关于指向 int 赋值的警告,即使使用显式转换,*((int *)y) = 3
也可能会收到关于“从不同大小的整数转换为指针”的警告。
推荐阅读
- python - C++ VTK 应用程序 UI 自动化
- c++ - 如何将 Rcpp::List 存储为类成员
- xpath - Xpath 在标签之间进行选择
- apache - apache2中conf、mods和站点的区别
- vert.x - PreparedStatement.close 抛出新的 IllegalStateException
- python - 如何以规则的行和列间隔拆分矩阵并将函数应用于每个拆分矩阵
- akka.net - Akka.NET - 如何抑制有意的子演员失败的记录?
- react-native - 无法在 React native 中创建长度超过 0x1fffffe8 个字符的字符串
- git - 如何连接本地仓库和远程仓库?
- mysql - 根据 case when 子句的条件执行不同的预处理语句