看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《littleshan (我要加入劍道社!)》之銘言: : 試圖寫入常數是 undefined behavior : 上述的 code 在 C++ 中甚至直接視為 compile error 如同各位大大指出,C99/C++03 中試圖寫入 const 的東西(object)都是 未定義行為(除了 C++ 中的 mutable)[1]. 在此想要多補充「未定義」的意 思:一個程式一旦含有「未定義的行為」,整個程式都沒有規定,而不是執行 到某行後程式才突然當掉或是有不可預期的結果。例如: | #include <stdio.h> | int main () { | int i = 0; | printf("debug\n"); | i = (i++) + (++i); /* undefined */ | return 0; | } 不代表會印出 debug 後才「出錯」,而是整個程式打從開始就沒有意義! 我想大家都知道未定義行為要避免,但可能沒有意識到會影響到「整個」程式。 如同其他大大指出,就算編譯後的程式,連 debug 都沒有印出來就開始格式化 你的硬碟,也完全正確。 之前發現兩篇有趣的 blog 文章給有興趣的人參考: http://blog.regehr.org/archives/213 http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html (第二篇簡直就是 LLVM 開發者的抱怨文 xD) : 推 XYX16888:我只是在做測試 故意寫錯 然後了解整個過程 二樓說的太 07/05 14:37 : → XYX16888:嚴重了吧@@ 07/05 14:37 也許別的語言可以,但可惜這種測試方法對 C/C++ 完全行不通。如果你 想了解「理論上」的行為,那麼只要有未定義行為,整個程式都不用討論了。 如果你想了解「真實」的編譯器到底會吐出什麼機械碼,恐怕請編譯器吐出組 語來比較快。現在常見的編譯器會用各種方法分析並改寫你的程式,希望能提 昇效能(也就是所謂的最佳化)。常常最後產生的程式,並不會真的依照你寫 的程式一步一步執行;編譯器只要讓正確的程式「看得到」的行為是對的就好, 無論用多難以想像的方法實作都沒有關係。所以我說,請編譯器吐出組語比較 快。希望這有回答到你的問題。 就我所知 Xcode 裡面用 gcc. 加上 -S 的參數應該可以輸出組語。可能 要請用 Xcode 的人更正我 xD [1] 條文見 C99 6.7.3 和 C++98 7.1.5.1 我不想再貼條文了 xD -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.30.39
angleevil:怎麼說呢?有時候未定意行為出現在兩個因素在.1.為了速度 07/05 17:33
angleevil:因此很多細節部分,不會額外幫你處理,因為還要幫你花時間 07/05 17:35
angleevil:檢查.2.歷史的問題,10年前有些規範還未訂好或技術還不到 07/05 17:38
angleevil:但是很多系統是以前延用到現在,c/c++標準委員會因此只 07/05 17:39
angleevil:能口頭勸導你不要這樣用.如果知道是UB時.個人心態是 07/05 17:41
angleevil:賺到了,趕快記下來,以後不要犯.因為當一個專案到10萬行 07/05 17:41
angleevil:要維護時,往往讓你爆肝就是魔鬼行為害的. 07/05 17:42
james732:樓上好像很有切身之痛........XD 07/05 17:45
angleevil:我只有不知道UB.行為才會犯到,我比較大的切身之痛是 07/05 17:48
angleevil:模組化和撰寫前未詳細理解要解決的問題,因此寫出不知道y 07/05 17:48
angleevil:輸出是對的程式.所以我對良好程式習慣很重視.我是走安全 07/05 17:49
angleevil:路線的設計者,跟個性有關連吧 07/05 17:50
michael0728n:我有問題! 那const是拿來做什麼用的@@" 07/05 20:16
michael0728n:日前的訓練告訴我const是防止自己不小心改了不能被改 07/05 20:17
michael0728n:的變數 如果不小心改了const 編譯時會被警告或不過 07/05 20:18
michael0728n:如果沒有這個好處在變數前加上const還有其他好處嗎? 07/05 20:19
如果你是指原原 PO 的例子,「正常」的編譯器應該都會警告你。然後 C++ 除非特別用轉型否則編譯器是要叫一下的(兩個語言對 const 的態度不 同)。也就是說 C++ 要特別寫下面這種程式碼,才能讓編譯器閉嘴: | const int var = 10; | int *vptr = const_cast<int*>(&var); 然後,請盡量不要仰賴編譯器會好心警告你。尤其 C 的精神前兩條是: | 1. Trust the programmer. | 2. Don't prevent the programmer from doing what needs to be done. | ... @ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1250.pdf 簡單來說,C 程式設計師是完全被信任的 :P 用 const 更像是對編譯器 發誓你絕對不會在初始化後改它。我不確定 C++ 對於 const 的態度該怎麼 用一句話總結 xD 有待高手補完。
littleshan:compiler可以利用常數性質進行最佳化 07/05 20:35
差不多是這樣...。
angleevil:我有問題,littleshan可以舉個小例子嗎?不然這句好抽象 07/05 20:58
james732:不就是上一篇文章講的嗎? 07/05 20:59
james732:printf("%d", var); 可以變成 printf("%d", 10); 07/05 20:59
james732:反正var不會變,這樣就不需要去讀取var的值了 07/05 21:00
angleevil:謝謝 07/05 21:14
※ 編輯: Favonia 來自: 140.112.30.39 (07/05 21:48)
michael0728n:理解!謝謝~ 07/05 21:32
再補一下,如果你是說這種: | const int x = 3; | x = 4; 所有正確的編譯器都要發出錯誤訊息!這點不用擔心!
purpose:JAVA 沒有 C++ 這樣的 const 概念,所以對於 const 就當作 07/05 21:58
purpose:有點用處,但也不是非用不可的東西就好了 07/05 21:58
Java 有 final, 某種程度上有點類似 const, 但意思不同(也有不同的 陷阱 orz)... 為了不離題我就不多講了 xDD
loveme00835:const也是介面規範之一 07/05 22:07
嗯... 補充一下,C++ 的 const 還會影響到初始化 xD(功力不夠不知 道怎樣一言以蔽之 orz) ※ 編輯: Favonia 來自: 140.112.30.39 (07/05 22:43)
VictorTom:也推:) 07/05 23:16
adrianshum:說起 Java final vs const 的話, Java 版我有回過一篇 07/06 08:57
※ 編輯: Favonia 來自: 140.112.30.39 (07/30 10:30)