最近在學習Nand Flash驅動程序設計時,涉及到((volatile unsigned long )),通過查閱部分網絡文章,對其用法和指針有了進一步理解,遂作此筆記。本文參考了yueleilei的文章--ARM定義特殊寄存器(*(volatile unsigned long *))的理解[點擊打開鏈接](http://bbs.ednchina.com/BLOG_ARTICLE_3002274.HTM),在此感謝。
## 一、對 #define SREG (*(volatile unsigned char *)0x5F)的理解
?? 嵌入式系統編程,要求程序員能夠利用C語言訪問固定的內存地址。既然是個地址,那么按照C語言的語法規則,這個表示地址的量應該是指針類型。所以,知道要訪問的內存地址后,比如0x5F,第一步是要把它強制轉換為指針類型(unsigned char *)0x5F,AVR的SREG是八位寄存器,所以0x5F強制轉換為指向unsigned char類型。
?? (注意,這一步的理解很關鍵,很多文章說:( volatile unsigned long * )的意思是將后面的那個地址強制轉換成 volatile unsigned long * ,當初看文章一直不理解這句話,其實解釋為:將(volatile unsigned long * )后面跟的內容轉化成一個指針,并且該指針指向一個易變的無符號整數,這樣更易理解。)
?? volatile(可變的)這個關鍵字說明這變量可能會被意想不到地改變,這樣編譯器就不會去假設這個變量的值了。這種“意想不到地改變”,不是由程序去改變,而是由硬件去改變——意想不到。
?? 第二步,對指針變量引用,就能操作指針所指向的地址的內容了
???? ? *(volatile unsigned CHAR *)0x5F
?? 第三步,小心地把#define宏中的參數用括號括起來,這是一個很好的習慣,所以
?????? #define SREG (*(volatile unsigned CHAR *)0x5F)
?? 類似的,如果使用一個32位處理器,要對一個32位的內存地址進行訪問,可以這樣定義
?????? #define RAM_ADDR (*(volatile unsigned LONG *)0x0000555F)
?? 然后就可以用C語言對這個內存地址進行讀寫操作了
?????? 讀:tmp = RAM_ADDR;
?????? 寫:RAM_ADDR = 0x55;
## 二、舉例
?? 例:如何理解(*(volatile unsigned long *)0x56000010)
?? 解答:
?????? long是32位整型,unsigned指無符號數,左邊的*表示取內容;
?????? volatile表示易變的,告訴編譯器不要優化,這個地址的內容不一定是在程序中改變的(可能是硬件上改變的,如寄存器中某些狀態位的改變);
?????? (volatile unsigned long *) 表示將后面跟的內容轉化成一個指針,并且是指向一個易變的無符號整數。左邊再加個,表示取該指針指向地址的內容。
??????總的意思是取那個內存單元(內存地址0x56000010)里存的數,并將這個數轉化為無符號整數。