当我使用*(int *)& x分配给常量值x时会发生什么?

时间:2017-10-16 00:31:56

标签: c++

我尝试过以下代码:

#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 ==&amp; x)是真的很奇怪但是(* p == *(&amp; x))是假的!!!我不知道第二个代码中发生了什么。

1 个答案:

答案 0 :(得分:2)

你正在做的是undefined behaviour,所以任何事情都可能发生。 C ++标准说:

  

除了可以修改声明为mutable(10.1.1)的任何类成员之外,任何在其生命周期内修改const对象的尝试(6.8)都会导致未定义的行为。

  

[注意:根据对象的类型,通过指针,左值或指向数据成员的指针的写入操作可以转移一个const限定符const_cast产生未定义   行为(10.1.7.1)。 - 结束说明]

所以你可以抛弃&#34; const&#34;获取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

在你的第二个例子中,编译器在优化时做出假设,基于它知道常量值不会改变的事实,所以它不会打扰测试它的值。这个假设是正确的,因为正确的程序永远不能改变常量的值。你的程序不正确,但这意味着编译器不需要给出合理的结果。