使用指针时的奇怪行为

时间:2012-11-08 23:41:13

标签: c++ pointers

当我在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指针的限制。”

我知道尝试修改常量在概念上是错误的,但我觉得这个结果很奇怪。任何人都能解释其背后的原因吗?

2 个答案:

答案 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。