2017-10-16 110 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 

在你的第二個例子優化當編譯器做的假設的基礎上,它知道一個事實常數值不會改變,所以它不會打擾測試它的價值。該假設是正確的,因爲正確的程序永遠不會改變常量的值。你的程序不正確,但這意味着編譯器不需要給出明智的結果。

相關問題