c++的強制類型轉換?
01-15
利用static_cast和reinterpret_cast是不能轉換const的常量,所以用c語言的強制類型轉換作了一下實驗:
const int a = 10; int *p = (int *)a;*p=9;
cout&<&然後結果是10 和9,然後覺得a和*p指向的應該是同一塊內存,但是輸出的結果不一樣。然後調試了一下a=(const int *) 0x22fe34*p=(int *) 0x22fe34*p=9
a=9到這就看不懂了,為什麼內存中顯示常量a=9,輸出a的值就變成10了 ?因為這是360的一道選擇題,所以嘗試下用(int*)修改一下,以前不知道。。
補充一句:UB 看彙編是無意義的。
首先,這是未定義行為。其次,這個問題已經被問了無數遍,你可以搜到答案。最後,這是 C++ 不是 C 。
編譯器編譯時將cout語句中的a自動替換成了常數,所以輸出了10
編譯優化,+ @Milo Yip 大神說得對
去看看編譯器生成的彙編代碼,你會發現cout在輸出a的時候並沒有讀取內存,而是直接在彙編里硬編碼了個立即數0x0a。
先看const int a = 10;這種編譯的時候就知道的常數往往會被編譯器優化掉,這是為了減少內存讀寫的次數。
a被優化後,所有用到a的地方都會被替換為數字0x0a,就不存在有內存地址了。再看int *p = (int *)a;你用了取地址操作a,即使沒有實際意義,但這個操作合法啊,編譯器為了讓這個操作有個結果,硬著頭皮在內存中給a賦予了一塊內存區域。然而,後面用到a的地方仍然不會取這個內存里的數值(因為編譯器覺得變數a既然是你欽定的const不會改變,當然吼啊,怎麼會不滋瓷對吧?於是編譯器繼續在後面的代碼中把a替換為0x0a),所以輸出是10。同理,inline修飾的內聯函數,雖然一樣沒有實際地址,但當你取一個inline函數的地址時,編譯器也不得不為這個inline函數在內存中存放一個函數體,只要你不通過地址去調用,基本沒有什麼時候會執行那段代碼。
然而。。。並不是所有C++編譯器在這種情況下都會採取一樣的優化策略。輸出9 9也是可能的,所以並沒有研究的意義。話說現在各種大學考試啊,面試啊,出題的都整這些未定義行為,到底想考查什麼,我可以文明用語嗎?學C++,有這功夫多鑽研一下C++新標準和各種best practices才是正途,不要為這些沒意義的牛角尖增加心智負擔,浪費時間!const的常量疊加問題,樓上 @王尼瑪 說的很對,簡單直接的方式是用彙編去追本溯源。也可以用本身const的屬性去解釋。const一部分的作用是替代C語言中的宏定義。宏定義的發生在預處理過程中。就已經完成了,所以,cout過程中,已經完成替換。取地址操作時,const在此處作為一個頂層指針,只能保證值不被修改,對地址是不做修飾的。原則上,這種舊式強制轉換,建議使用const_cast類型轉換。
推薦閱讀:
※對於 計算機圖形/界面/可視化/遊戲畫面/遊戲引擎 的疑惑?
※VS編寫C++程序,如何在一個工程裡面創建多個包含main函數的文件?
※c++的单例模式为什么不直接全部使用static,而是非要实例化一个对象?
※「Bjarne 為增加 C++ 程序員身價有意增加 C++ 難度」是否屬實?
※這種寫法用意何在?
TAG:C |