C語言疑難雜症-指針
\\\插播一條:文章末尾有驚喜喲~///
進修階段:高中信競、大學編程。
前置知識:二進位與十六進位,C語言根底,數組。
指針初學可能比較難了解,我這篇文章儘量用通俗易懂的方式來講解。
1.指針概述
為什麼有指針這個東西?由於指針很貼近計算機內部的實際工作原理,與內存實際的尋址方式類似。C語言能夠說是高級語言中最貼近機器的語言,而像Python、JavaScript這種更親和於人類的語言與機器的關係則比較遠了,甚至它們自身可能還是用C語言寫出來的呢。
指針能夠形象地比喻為在內存中定位的導航員。內存那麼大,怎麼知道我須要的東西存在哪裡呢?能夠讓指針來記錄與導航。我們先來了解一下內存。
2.預備知識
2.1內存
鑽研過組裝機、電腦配件的話,一定知道內存條這個東西。此時這個時代,一台家用電腦的內存一般是2GB、4GB、8GB、16GB、32GB、64GB等等。
把CPU比作幹活的人,則內存就相當於工作檯。CPU在跑的程序以及很多相關數據都存在內存內,這就相當於人在幹活時要把相關資料放在工作檯上使用。
內存能夠看成是一個宏大的數組,我這裡記為
memory[0..n]
memory的每一個單元存1B=8bit,memory[0]就是內存的第一個單元。這個中括號裡面的數,即數組下標,被稱為內存地址,簡稱為地址。我確定了一個地址,也就相當於確定了內存中的一個單元。
通常,我們說的32位機器,意思就是地址是32bit的,最大支持的內存是
memory[0x00000000..0xFFFFFFFF]
最小地址是0,最大地址是0xFFFFFFFF=2^32-1,最大支持
也就是說32位機器理論上最大支持4GB的內存,這就是它漸漸被淘汰的理由。
而64位機器理論上最大支持的內存是
這個量級遠大於目前的需求,因此128位機器在相當長的時長內不會出現。
2.2變量與數據類型
C語言有很多數據類型,不同的數據類型在內存中的占用空間和存儲格式也不一樣。不同數據類型的存儲格式比較複雜,這裡不詳述。我只談談不同的占用空間。
一個變量在內存中占用都是不間斷空間,記T類型的變量在內存中占用sizeof(T)位元組的空間。當我聲明一個T類型的變量a時,內存會尋找不間斷且可用的sizeof(T)個單元,把它們分配給變量a,假如說是memory[100..103]這4B的空間。此後我對變量a進行讀寫,也就相當於對memory[100..103]這4B的空間進行讀寫。
某些數據類型的占用空間:short短整形占用2B,int整形占用4B;float浮點形占用4B,double雙浮點型占用8B;char字符型占用1B.
3.指針
指針是一種特殊的數據類型,指針類型的變量應存儲的是內存地址。在32位機器上,任何一個內存地址都是32bit=4B,故任何一個指針型變量都占用4B.
此時問題來了,指針指向內存中的一個單元,我怎麼知道這個單元裡面存的是什麼東西,是什麼類型的數據?因此,在聲明指針變量的時候,也要聲明這個指針指向數據的類型,假如int型指針、char型指針等。
3.1指針的聲明
在語法上,聲明指針類型使用*符號,例如
int *a, b, *c; //a和c是指針,b不是指針char *ch;
這兩句代碼聲明了int*型的變量a與c、int型變量b以及char*型變量ch.依據語法,我們習慣上稱T型指針為T*型,含義就是T*型變量是指針,其所指的相關內存單元存的是T型數據。(注意,這裡的b變量不是指針,僅僅為普通的int整形。)
3.2指針的使用
指針有很多種使用方式,包括動態申請內存、函數地址傳參等等。我這裡僅介紹最簡略的使用方式。我提供一份例程,可直接從例程中進修指針的聲明與使用。
例程:
int x=1, y=2; //聲明x與y並賦初值int *p=&x; //聲明p且p指向x*p=11; //p修改xp=&y; //p指向y*p=12; //p修改yprintf("x=%d, y=%d", x, y); //打印x與y
第一行,在內存中申請不間斷的4B區域存入int型數據1,記為變量x;再在內存中申請不間斷的4B區域存入int型數據2,記為變量y.假設x對應內存區域memory[100..103],y對應內存區域memory[200..203].第一行執行完畢,內存如圖1所示:
圖1第一行執行完畢
第二行,在內存中申請不間斷的4B區域存入int*型地址數據100,記為變量p.這里&符號是取地址運算符,表示取變量x的首地址,在本例中就是100.這一行代碼是聲明指針同時賦初值,相當於以下兩行代碼:
int *p;p=&x;
第二行執行完畢,內存如圖2所示(100的十六進位是0x64):
圖2第二行執行完畢
第三行,將p所指的地址起4B空間內存入int型數據11.這里*是解地址運算符,表示取得指針所指的內存空間。第三行執行完畢,內存如圖3所示:
圖3第三行執行完畢
假如第三行改為執行p=(int*)11;,則是先把int型數據11強制轉換為int*型數據11,然後賦值給p,如圖3.2所示:
圖3.2第三行改為執行p=(int*)11;
此時p所指的內存空間不一定是可用的。因此像這樣直接給指針賦值一個常數的情況非常罕見。
第四行,p存y的首地址。第四行執行完畢,內存如圖4所示:
圖4第四行執行完畢
第五行,把變量y的值改為12.第五行執行完畢,內存如圖5所示:
寫文章
Keil系列教程09_調試仿真
strongerHuang
?關注他
44人贊同了該文章
說明:
本文原創作者『strongerHuang』
首發於微信公眾號『嵌入式專欄』,同時也更新在我的個人網站:EmbeddedDevelop
標籤:Keil、 MDK-ARM、μVision
該教程基於MDK-ARM,大局部內容也適用於Keil其它3款(C51、 C251、 C166)產品。
一、寫在前面
調試對於程式設計師來說是一個比較重要的環節,因此就很有必要掌握Keil的這些調試功能。
點擊Debug調試按鈕,進入調試狀態,就會出現如下圖Debug Toolbar調試工具欄。
我們調試須要用到的按鈕包含上圖框出來的這些按鈕,但常用的按鈕就是調試工具欄前八個:復位、全速運行、停下運行、單步運行、逐步運行、跳出運行、運行到光標行、跳轉到暫停行。
二、相關描述
這些工具欄按鈕的主要含義能夠參看《Keil系列教程03_主窗口和工具欄詳細說明》。
調試工具欄按鈕位於菜單Debug中,同時調試視圖窗口位於菜單View。能夠參看文章《Keil系列教程04_菜單概述》。
同樣,這些調試工具欄按鈕可通過快速鍵實現,有些默認沒有快速鍵,能夠通過Configuration添加快速鍵。請參看文章《Keil系列教程08_Configuration(二)》Shortcut Keys快速鍵章節內容。
下面率領大家掌握那八個調試按鈕、四個斷點按鈕,以及局部調試視圖窗口的內容。
三、八個調試按鈕
保證代碼編譯沒誤,點擊「啟動/停下調試」按鈕(如下圖),或快速鍵Ctrl + F5,進入調試模式。此時就會出現如文中開頭的調試工具欄。
3.1 Reset復位
Reset復位,讓程序復位到起點,恢復到初始狀態。
3.2 Run全速運行
Run全速運行(F5),讓程序處於運行狀態。此按鈕在程序停下運行時有效。
3.3 Stop停下運行
Stop停下運行,讓正在運行的程序停下下來。此按鈕在程序運行時有效。
3.4 Step單步運行
Step單步運行(F11),每點一次按鈕,程序運行一步(單步),遇到函數會跳進函數執行(箭頭進入括號)。此按鈕在程序停下運行時有效。
3.5 Step Over逐步運行
Step Over逐步運行(F10),每點一次按鈕,程序運行一行(單行),遇到函數跳過函數執行(箭頭跳過括號)。此按鈕在程序停下運行時有效。
3.6 Step Out跳出運行
Step Out跳出運行(Ctrl + F11),每點一次按鈕,程序跳出當前函數執行(箭頭跳出括號),直到跳出最外面的函數(main函數)。此按鈕在程序停下運行時有效。
3.7 Run to Cursor Line運行到光標行
Run to Cursor Line運行到光標行(Ctrl + F10),將光標放在某一行,點擊該按鈕,程序全速運行,直到運行到光標的位置停下下來。(前提是程序能運行到光標所在行)。
3.8 Show Next Statement跳轉到暫停行
Show Next Statement跳轉到暫停行,點擊該按鈕,跳轉到程序暫停(停下)所在行。主要用我們翻開多個文件,不知道程序暫停在哪裡。此按鈕在程序停下運行時有效。
四、四個斷點按鈕
調試時,這四個按鈕也常用,從左到右依次是:插入/移除斷點、使能/失能斷點、失能所有斷點、取消所有斷點。
4.1插入/移除斷點
Insert/Remove Breakpoint插入/移除斷點(F9),點擊一下按鈕,在光標所在行插入一個斷點,再點擊一次,則移除斷點。
該按鈕操作即是用滑鼠在代碼所在行前面點擊一次,注意獨有在灰色所在行才有效(也就是程序能執行的地方),如下圖:
4.2使能/失能斷點
Enable/Disable Breakpoint使能/失能斷點(Ctrl + F9),在有斷點根底上,點擊一下按鈕,失能該斷點,再點擊一次,則使能該斷點。
失能斷點就是保留該斷點,但該斷點沒效(程序執行到該處不停下)。
4.3失能所有斷點
Disable All Breakpoints失能所有斷點,保留所有斷點,但都沒效(和上面一個道理),但這裡不能再次使能所有斷點。
4.4取消所有斷點
Kill All Breakpoints取消所有斷點(Ctrl + Shift + F9),和上面失能不一樣,這裡是不保留斷點,即取消工程所有斷點,也叫殺掉所有斷點。
五、調試視圖窗口
調試視圖窗口獨有進入調試模式時才會出現,其窗口名稱詳情可參看文章《Keil系列教程04_菜單概述》中View菜單章節。
這裡講述幾個在調試時常用的視圖窗口。
5.1 Watch窗口
Watch查看變量的窗口,有Watch1和Watch2兩個窗口,都一樣,方便用戶多個窗口同時查看。
查看這些調試視圖窗口能夠通過菜單,或點擊工具欄按鈕翻開。
選中變量 ->右鍵 -> Add 『xxx』 to ->Watch1,此時自動會彈出Watch1窗口:
5.2 System Viewer窗口
System Viewer系統(外圍IO、USART、TIM等)窗口,能夠了解查看外設寄存器的窗口,如下圖,查看USART寄存器值的窗口。
這些調試視圖窗口只針對於調試時,方便大家查看一些調試信息,掌握這些內容會提高你的調試效率,以及更精確定位Bug。
六、說明
1.該文檔僅供個人進修使用,版權所有,禁商用。
2.本文由我一個人編輯並整理,難免存在一些錯誤。
彩蛋:最近有同學跟我要單片機的資料,我特意花幾個月時間,總結了我10年產品研發經驗,資料包幾乎覆蓋了C語言、單片機、模電數電、原理圖和PCB設計、單片機高級編程等等,非常適合初學者入門和進階。除此以外,再含淚分享我壓箱底的22個熱門開源項目,包含源碼+原理圖+PCB+說明文檔,不是市面上打包賣的那種課程,我認為教程多未必是好事,10年前我自學快,除了自身執行力以外,還有就是教程少。不要害羞做伸手黨,等你一個小紅點。後期我也會組建一些純技術交流的小圈子,讓大家能認識更多的大佬,有個好的圈子,你對行業的認知一定是最前沿的。