为啥首先允许指针从非常量到常量的隐式转换?
Posted
技术标签:
【中文标题】为啥首先允许指针从非常量到常量的隐式转换?【英文标题】:Why is an implicit conversion from non-const to const allowed for pointers in the first place?为什么首先允许指针从非常量到常量的隐式转换? 【发布时间】:2016-08-24 13:32:22 【问题描述】:我了解在处理值时从 non-const
到 const
的隐式转换并不危险,例如:
int mutable = 5;
const int immutable = mutable;
但是,在使用指针时,我可以执行以下操作:
int some_number = 5;
int *mutable = &some_number;
const int *immutable = mutable; // <= Legal, but isn't it dangerous?
// Let's try to break const
printf("%d\n", *immutable); // Prints 5
mutable[0] = 10;
printf("%d\n", *immutable); // Prints 10
顺便说一句,对于双指针,这是不允许的(至少你会得到一个警告)!请参阅this 问题和其中的参考资料。
【问题讨论】:
常量指针的常见用例是作为函数参数。这告诉函数的用户(以及编译器)该函数不会改变指针指向的数据。 您的示例没有“破坏 const”,因为被修改的对象 (some_number
) 不是 const。在指针目标上使用 const 并不意味着“如果你读了两次就保证产生相同的值,中间还会发生一些其他的事情”
将const
视为承诺。为什么有人要违背自己的诺言?
您的代码中没有const
限定指针!
@Olaf:这不是重点,而是基础价值的变化
【参考方案1】:
来自the C11 standard (draft N1570):
6.7.3 类型限定符
语法
类型限定符:
const
restrict
volatile
_Atomic
[...]
语义:
与限定类型关联的属性仅对左值表达式有意义。
[...]
示例 1
声明的对象
extern const volatile int real_time_clock;
可由硬件修改,但不能分配、递增或递减。
简单来说:
const
并不意味着值永远不会改变。这只意味着你不允许改变它1.
对于被调用者,const
是一个限制,而不是一个承诺。
然而,对于调用者,它是一个承诺。将const
指针传递给函数,您可以放心地假设该函数不会更改您的数据2,因此是“向您做出承诺”。
1 ...通过带有const
限定符的标识符。2 ...通过传递给它的const
参数。
【讨论】:
我忘了说我用的是C99,但我猜那里的标准是相似的。感谢您的澄清! 但奇怪的是,对于双指针,确实会发出警告,以防止我刚才对单指针所做的事情,请参阅c-faq.com/ansi/constmismatch.html "只表示不允许你修改。" - 甚至没有!我的意思是程序员保证不会修改它。 将 const 指针传递给函数,您可以放心地假设该函数不会更改您的数据,因此是“向您做出承诺” 这是不正确的,该函数仍可能通过全局值的其他参数更改数据。 这不是答案中写的。您的评论补充说:通过该论点,这是一个重要的区别。以上是关于为啥首先允许指针从非常量到常量的隐式转换?的主要内容,如果未能解决你的问题,请参考以下文章
为啥允许从 int 到 byte 但不允许从 long 到 int 的隐式缩小转换?
在构造 std::variant 时禁用从指针类型到 bool 的隐式转换的最佳方法是啥?
ARC 中不允许从 NSInteger 到 NSString 的隐式转换.. 应该使用啥解决方法来处理整数