2017-10-16 71 views
-3

我曾尝试以下代码:当我使用*(int *)&x分配一个常量值x时会发生什么?

#include <iostream> 
using namespace std; 
struct MyClass { 
    const int x; 
}; 
int main() { 
    MyClass c = {3}; 
    const int *p = &c.x; 

    cout << "x = " << c.x << endl; 
    cout << "&x = " << &c.x << endl; 
    cout << "p = " << p << endl; 
    cout << "*p = " << *p << endl; 
    cout << "*(&x) = " << *(&c.x) << endl; 
    cout << endl; 

    *(int*)&c.x = 4; 

    cout << "x = " << c.x << endl; 
    cout << "&x = " << &c.x << endl; 
    cout << "p = " << p << endl; 
    cout << "*p = " << *p << endl; 
    cout << "*(&x) = " << *(&c.x) << endl; 

    cout << (p == &c.x) << endl; 
    cout << (*p == *(&c.x)) << endl; 

    return 0; 
} 

然后我得到以下答案:

x = 3 
&x = 0x61fe98 
p = 0x61fe98 
*p = 3 
*(&x) = 3 

x = 4 
&x = 0x61fe98 
p = 0x61fe98 
*p = 4 
*(&x) = 4 
1 
1 

看来,我已经成功地改变常数整数x的值。但是当我直接在main()中声明x而不是在类中时,我得到了完全不同的答案。

#include <iostream> 
using namespace std; 

int main() { 
    const int x = 3; 
    const int *p = &x; 

    cout << "x = " << x << endl; 
    cout << "&x = " << &x << endl; 
    cout << "p = " << p << endl; 
    cout << "*p = " << *p << endl; 
    cout << "*(&x) = " << *(&x) << endl; 
    cout << endl; 

    *(int*)&x = 4; 

    cout << "x = " << x << endl; 
    cout << "&x = " << &x << endl; 
    cout << "p = " << p << endl; 
    cout << "*p = " << *p << endl; 
    cout << "*(&x) = " << *(&x) << endl; 
    cout << endl; 

    cout << (p == &x) << endl; 
    cout << (*p == *(&x)) << endl; 

    return 0; 
} 

结果是

x = 3 
&x = 0x61fe98 
p = 0x61fe98 
*p = 3 
*(&x) = 3 

x = 3 
&x = 0x61fe98 
p = 0x61fe98 
*p = 4 
*(&x) = 3 

1 
0 

那可真是奇怪,(P == & x)是真实的,但(* P * ==(& X))是假的!我不知道第二个代码是怎么回事。

+3

找到一位新教授。不要从你现任教授那里学到任何东西。 –

回答

2

你在做什么是undefined behaviour,所以什么都可能发生。 C++标准表示:

除了任何类成员声明mutable(10.1.1)可以被修改,任何试图其寿命(6.8)导致未定义的行为过程中修改一个const对象。

和:

[注:根据对象,通过指针,左值或指针数据成员从该const_cast蒙上离开的const-所得的写操作的类型限定符可能会产生未定义的 行为(10.1.7.1)。 - 注完]

所以,你可以抛弃“常量”来获得int*但试图实际上通过该指针修改的变量是不确定的。

你可以丢掉const的原因是,它可能实际上并不指向一个常数:

int i = 0; 
const int* p = &i; 
*(int*)p = 1;  // OK, because p points to a non-constant 
const int j = 0; 
const int* q = &j; 
*(int*)q = 1;  // NOT OK, because q points to a constant 

在你的第二个例子优化当编译器做的假设的基础上,它知道一个事实常数值不会改变,所以它不会打扰测试它的价值。该假设是正确的,因为正确的程序永远不会改变常量的值。你的程序不正确,但这意味着编译器不需要给出明智的结果。

相关问题