Const
const:限定一個變數不允許改變,產生靜態作用,const在一定程度上可以提高程式的安全性和可靠性。
const 推出的初始目的,正是為了取代預編譯指令,消除它的缺點,同時繼承它的優點。宏定義:
#define xxxx { xxx }
後不能有任何字元,包括空格 最後的 “}”需要最少空一行
struct xxxx xxx = {.x1 = xxxxx,.x2 = xxxxx,.x3 = xxxxx};
在C99模式下可以使用該方式對結構體進行初始化,方便觀察每一個變數的初始值。
宣告為const的變數是不能被使用者改變的,因為編譯器會將該變數放在只讀區,比如在KEIL開發平臺下,宣告為const的變數放在FLASH區,這樣即使你使用取地址符 & 獲取宣告為 const 變數地址,並透過指標進行修改,雖然編譯器不報錯,但也是無法進行修改的,因為進行FLASH程式設計是有條件的。
image.png
你會發現雖然P獲取了N的地址,但因為N存放在FLAH中,所以透過指標也是無法改變N的值的。
image.png
可以看到N沒有改變。但是編譯器確實也沒報錯。但是如果你直接 N = 4 的話,肯定是報錯的,因為你的N被申明為const。
image.png
《C語言深度剖析》中關於const的介紹發現和KEIL情況不一樣。
image.png
在KEIL中進行相關程式碼的編寫,編譯,最後可以看到如下結果:
image.png
這是模擬模式下兩個地址的內容,一個存放在FLAH,一個存放在RAM中,並且當修改FLAH的內容之後(因為是軟體模擬模式,可以直接修改值),復位重新執行,你會發現RAM的內容對應改變了(重新執行後,進入main函式之前,有一段複製程式碼,就是函式外申明的一些變數的初始化過程),這就說明,在STM32、KEIL環境下,並不是《C語言深度剖析》中說的只有一份記憶體,而是每一個都有一個,申明為const情況跟使用宏定義的方式是一樣的。
以下是Watch中的內容
image.png
但其實上面的結論是在使用 & 將N的地址獲取後的結果(從上圖可以看到p的值),實際上程式碼中如果沒有獲取N的地址時,情況又不一樣了。
記憶體情況:
image.png
在刪去獲取N地址後的記憶體情況,可以發現N的值為0x2000470,和FLAH地址0x08000000一樣。
image.png
這像一個地址。但透過Memory檢視這個地址發現存放的不是5。
image.png
根據ARM核心的知識可以知道,0x08000000地址存放的其實是棧頂指標,也就是說N存放的是棧頂指標嗎?顯然不是。
然後對.map地址對映檔案進行搜尋,你會發現,根本沒有N的地址。這樣說來,N在記憶體的位置對使用者是不可見的,而是由編譯器自動處理了。
那麼有沒有辦法找到這個複製源頭呢。之前我說過,先前能找到複製的源頭純屬偶然,有沒有什麼方法可以找到呢?這其中的難點就是進入main函式之前的那段複製程式碼不是我們使用者自己寫的,而是C編譯器自動處理的,怎麼辦?
這個時候就需要請出一個關鍵人物:資料觀察點(關於資料觀察點,將有專門的一小節詳細說明)。
我們知道,不管如何,因為FLASH存放著變數初始值,然後在程式執行的時候才將FLASH中的值初始化到RAM中去,也就是我們使用的RAM變數,那麼必然存在透過匯流排進行資料傳輸的過程,所以可以透過資料觀察點的功能實現對地址的監控,雖然我們不知道FLAH的地址,但是我們知道RAM的地址,所以只要對變數i進行監控,就可以透過核心的暫存器找到FLASH地址了。如下:
image.png
這裡的0x20000000就是i的RAM地址,最終可以找到FLASH的位置:
image.png
由此可以知道,FLAH中也是有多個相同副本存在的。
因此可以得出結論,在STM32、KEIL的環境下,《C語言深度剖析》對於兩者的說法在這裡不適用。
看了那麼多,沒有足夠的基礎是很難知道我在講什麼的,下面用一張圖進行說明,希望可以解答你的疑惑。
作者:EmbeddedOsprey
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4369/viewspace-2820894/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- const * and * const
- const char*, char const*, char*const 有何區別?
- 頂層const和底層const
- 搞懂頂層const和底層const
- C++ 頂層const底層constC++
- JavaScript ConstJavaScript
- const 使用
- C語言 關鍵字const的作用 const int* 和int *const 的區別C語言
- JavaScript const 命令JavaScript
- let和const
- const和define
- 07-const
- C++ 中的 const 物件與 const 成員函式C++物件函式
- SyntaxError: Unexpected keyword 'const'?Error
- 指標與const指標
- let var與const
- Const 用法總結
- let與const命令
- const關鍵字
- const限定符
- inline、const、mutable、this、staticinline
- let與const區別
- C++基礎 constC++
- var let const區別
- let const var 區別
- C++ const 總結C++
- C/C++const用法C++
- C++ constexp vs constC++
- const char*的全特化
- const {xxx} = this 是什麼?
- 基礎之const解析
- let,const,var區別
- JavaScript 高階—— ES6新增語法 const(let const var區別)JavaScript
- 【C++100問】深入理解理解頂層const和底層constC++
- C++中const的用法C++
- const與static的區別
- ES6 let和const
- 引入const成員函式函式