当我在MS VS C ++ 2010上运行此代码时:
#include <iostream>
int main() {
const int a = 10;
const int *b = &a;
int *c = (int *)b;
*c = 10000;
std::cout << c << " " << &a << std::endl;
std::cout << *c << " " << a << " " << *(&a) << std::endl;
return 0;
}
输出结果为:
0037F784 0037F784
10000 10 10
编写该代码的动机是Stroustrup的“C ++编程语言”中的这句话: “可以通过显式类型转换显式删除对const指针的限制。”
我知道尝试修改常量在概念上是错误的,但我觉得这个结果很奇怪。任何人都能解释其背后的原因吗?
答案 0 :(得分:7)
让我们从显而易见的开始:其中一些是依赖于平台和编译器的。
对于初学者,请参阅Explicit Type Conversion上的这篇文章,特别是:
指向
const
类型对象的指针可以转换为指向a的指针 非const
类型。 生成的指针将引用原始指针 object。const
类型的对象或对象的对象的引用const
类型可以转换为对非const
类型的引用。该 结果引用将引用原始对象。 结果 试图通过这样的指针或引用修改该对象 将导致寻址异常,或者与...相同 原始指针或引用引用了非const对象。它是 实现取决于是否发生寻址异常。
所以这就解释了为什么可能允许你修改变量而没有婊子。
请注意,您可以直接使用强制转换操作符来实现相同的操作,因为这是编译器将按照此article on cast operators中的说明为您执行的操作,并给出了它们的优先顺序。
然而,真正的技巧是在内存模型中。静态分配的变量,如const int a,实际上可能永远不会在内存中有任何“物理”位置,并且只是替换为编译时间。 (我试着把手指放在实际参考上,但到目前为止,我能抓到的最接近和最好的是(非常好)SO answer到 is memory allocated for a static variable that is never used? - 如果有人找到实际参考资料,请告诉我们。)
所以这里的编译器只是在嘲笑你,并试图尽可能多地理解你的指针运算,但最终会替换a
第二个cout
的最后两个部分{{1}}的实际值。 1}}来电。
答案 1 :(得分:0)
原因是这是未定义的行为。
Stroustrup引用可能是指未声明对象const
但是只有const
指针的情况。
即。这是明确定义的(使用c样式转换,因为它们出现在问题中):
int a{10};
const int* pa = &a;
int* b = (int*)pa;
*b = 5;
这是未定义的:
const int a{10};
const int* pa = &a;
int* b = (int*)pa;
*b = 5;
尝试修改声明为const
的对象,但是你得到一个非常量指针,是UB。