3

可能重复:
C/C++ 更改 const 的值

以下程序:

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

给出以下输出:

10
12

将 &x 转换为 (int *) 有什么影响,为什么 x 的值仍然是 10 ?我预计是12。

另一个疑问

为什么我们不能将 say 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

4 回答 4

8

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

正如我在评论中指出的那样:

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

cout << 10 << endl;

代替:

cout << x << endl;

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

cout << 12 << endl;

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

于 2012-05-11T15:06:28.260 回答
2

编译器将在分配给const int. 实际上,您的程序如下所示:

        cout<<10<<endl;
        cout<<*p<<endl;
于 2012-05-11T15:03:10.560 回答
1

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

对于第二个问题,请考虑如果允许,您可能会无意中破坏 const-correctness:

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 正确性.

于 2012-05-11T15:48:40.853 回答
0

嗯,这是个有趣的问题。当您删除 x 的 const 前缀时,您将获得所需的结果。

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

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

于 2012-05-11T15:29:00.097 回答