指针铸造没有给出预期的结果

时间:2012-05-11 14:58:30

标签: c++ pointers

  

可能重复:
  C/C++ changing the value of a const

以下计划:

int main()
{
    const int x = 10;
    int * p = (int *)&x;
    *p = 12;
    cout<<x<<endl;
    cout<<*p<<endl;
    return 0;
}

输出:

10
12

cast&amp; x对(int *)的影响是什么?为什么x的值仍为10? 我预计它会是12岁。

另一个疑问

为什么我们不能把int **说成int const **? 相反,此操作有效

void f(int const ** p);
void g(int const * const * p);

int main()
{
    int ** p = /*....*/
    f(p);   //Error
    g(p);   //OK
}

请用合适的例子帮助我理解这一点 谢谢!!!

4 个答案:

答案 0 :(得分:8)

您正在通过修改声明为const的变量来调用未定义的行为。任何结果都是程序的合法输出,尽管有些结果比其他结果更合理。

正如我在评论中所说:

10可能是由于优化;编译器知道x是const,因此它可以调用:

cout << 10 << endl;

而不是:

cout << x << endl;

不太清楚的是编译器是否将第二个输出优化为:

cout << 12 << endl;

您必须查看生成的汇编程序才能确定。但由于整个程序正在调用未定义的行为,因此编译器是正确的,无论它是什么。

答案 1 :(得分:2)

当编译器分配给const int时,编译器将替换文字值。实际上你的程序看起来像:

        cout<<10<<endl;
        cout<<*p<<endl;

答案 2 :(得分:1)

从主要问题来看,已经回答:修改常量对象是未定义的行为。

对于第二个问题,请考虑如果允许的话,你可能会无意中破坏const正确性:

const int k = 10;
void f(int const ** p) {
    *p = &k;                   // Valid, p promises not to change k
}
void g(int const * const * p);

int main()
{
    int *p;
    int ** pp = &p;
    f(pp);                     // If allowed: p points to k!!!
    p = 5;                     // Modifying a constant object!!!
    g(pp);                     //OK
}

g的情况下,因为函数的签名承诺不会更改中间指针,编译器知道g不会修改*pp,这意味着它不能使*pp(即p)指向一个常量对象,并保证const正确性。

答案 3 :(得分:0)

好吧,这是一个有趣的问题。 当你删除x的const前缀时,你会得到你想要的结果。

int main()       
{               
 int x = 10;               
 int * p = (int *)&x;               
 *p = 12;              
 cout<<x<<endl;              
 cout<<*p<<endl;               
 return 0;      
}

我认为这是const标记阻止x值的变化。