




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、嵌入式系統(tǒng)C語言編程基礎楊高波SNBCPage 2目錄 關于本課程 C語言復習 編程規(guī)范 開發(fā)高效程序的技巧Page 3為什么學習本課程 會C語法與會用C語言寫程序是兩個概念 C的靈活性以及由此而產生的陷阱非常多 The Most Beautiful Language and Most Dangerous Language in the Programming World! 本課程將嵌入式系統(tǒng)中最基本的(最經常用到的)概念與技巧介紹給大家Page 4小測驗?Page 5Quiz 1 所有嵌入式系統(tǒng)的主流程最后都進入一個死循環(huán),怎樣用C語言實現一個死循環(huán)?Page 6Quiz 2 while()
2、.和do.while()有什么區(qū)別?Page 7Quiz 3用變量a給出下列定義:a) 一個整型數b) 一個指向整型數的指針c) 一個有10個整型數的的數組d) 一個有10個指針的數組,該指針是指向一個整型數的Page 8Quiz 4 關鍵字static的作用是什么?Page 9Quiz 5 關鍵字const的作用是什么?Page 10Quiz 6 定義一個標準宏MIN ,這個宏輸入兩個參數并返回較小的一個。Page 11Quiz 7 嵌入式系統(tǒng)中經常要對變量或寄存器進行位操作。給定一個int型變量a,寫兩段代碼,第一個將a的bit 3置為1,第二個將a的bit 3置為0。以上兩個操作中,要保
3、持其它位不變。Page 12Quiz 8 嵌入式系統(tǒng)具有經常去直接訪問物理地址的特點。在某工程中,要求設置一絕對地址為0 x5a00 的整型變量的值為0 xaa55。寫代碼去完成這一任務。Page 13Quiz 9 下面這段代碼的輸出是什么?void foo(void)unsigned int a = 6;int b = -20;(a+b 6) ? puts(6) : puts(6);Page 14Quiz 10 請評論下面一段程序代碼:void test()char string10;char *str = “0123456789”;strcpy(string,str);Page 15Qui
4、z 11 請評論下面一段程序代碼:void GetMemory(char *p)p = (char *)malloc(0 x20);void Test(void)char *str = NULL;GetMemory(str);strcpy(str,”Hello World!”);printf(str);Page 16Quiz 12 中斷是嵌入式系統(tǒng)的重要組成部分。請評論下面一段中斷服務子程序代碼:_interrupt double compute_area (double radius)double area = PI * radius * radius;printf(nArea = %f,
5、area);return area;Page 17Answer!Page 18Quiz 1 Answer while(1).Page 19Quiz 2 Answer while().為入口條件循環(huán),即在每次執(zhí)行循環(huán)之前先檢查判斷條件;do.while()為退出條件循環(huán),即在執(zhí)行循環(huán)之后再檢查判斷條件。Page 20Quiz 3 Answer a) int a;b) int *a;c) int a10;d) int *a10;Page 21Quiz 4 Answer 在C 語言中,關鍵字static 有三個明顯的作用:1) 在函數體內,一個被聲明為靜態(tài)的變量在這一函數被調用過程中維持其值不變。2
6、) 在模塊內(但在函數體外),一個被聲明為靜態(tài)的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。3) 在模塊內,一個被聲明為靜態(tài)的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地范圍內使用。Page 22Quiz 5 Answer const是constant的縮寫,“恒定不變”的意思。被const修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。 const常量與#define常量:前者有數據類型,后者只是字符替換(而且可能產生意料不到的錯誤),所以編譯器可以對前者進行安全性檢查。Page 23Quiz 6 An
7、swer #define MIN(A,B) (A) = (B) ? (A) : (B) #define宏的副作用,下面的代碼執(zhí)行后會發(fā)生什么事:least = MIN(*p+, b);Page 24Quiz 7 Answer const int BIT3 = 0 x016”,原因是當表達式中存在有符號類型和無符號類型時所有的操作數都自動轉換為無符號類型。 因此-20 變成了一個非常大的正整數,所以該表達式計算出的結果大于6。這一點對于頻繁用到無符號數據類型的嵌入式系統(tǒng)來說是豐常重要的。Page 27Quiz 10 Answer 字符串str需要11個字節(jié)才能存放下(包括末尾的0),而strin
8、g只有10個字節(jié)的空間,所以strcpy會導致數組越界。 Page 28Quiz 11 Answer 編譯器總是要為函數的每個參數制作臨時副本,指針參數p的副本是_p,編譯器使 _p = p。本例中,_p申請了新的內存,但只是_p的值改變了,p的值卻絲毫未變,仍然為NULL。事實上,每執(zhí)行一次GetMemory就會泄漏一塊內存。Page 29Quiz 12 Answer 1)ISR不能返回值;2)不能向ISR傳遞參數;3)ISR應該是短而有效率的,因而在ISR中做浮點運算、使用printf等是不明智的,會經常有重入和性能上的問題。Page 30還是先復習一下C吧!Page 31C語言復習 1)
9、循環(huán)與分支2)作用域與存儲類3)內存與指針4)位操作5)預編譯處理Page 32循環(huán)與分支 1)幾種循環(huán)語句:for(initialize;test;update)body;while(test)body;dobody;while(test); 2)循環(huán)輔助手段:break語句用于跳出循環(huán),continue語句用于結束本次循環(huán)。Page 33循環(huán)與分支 3)三種形式的if語句:if(expression).if(expression).else.if(expression1).else if(expression).else.Page 34循環(huán)與分支 4)條件運算符?:expression1
10、? expression2 : expression3 如果expression1為真,整個表達式的值為expression2的值,否則為expression3的值; 是if.else.的簡寫形式,但是編譯器可以產生比if.else.更優(yōu)化的代碼。Page 35循環(huán)與分支 5)多重選擇:switchswitch(expression)case constant1: statements; break;case constant2: statements; break;.default: statements; break;switch判斷表達式必須具有整數值,case標簽必須是整數常量或整數常
11、量表達式。Page 36C語言復習 1)循環(huán)與分支2)作用域與存儲類)作用域與存儲類3)內存與指針4)位操作5)預編譯處理Page 37作用域與存儲類 1)作用域 代碼塊作用域(局部變量)代碼塊:包含在開始花括號和對應結束花括號之內的一段代碼。作用域:從定義變量位置到該代碼塊的末尾。 文件作用域(全局變量)在所有函數之外定義的變量具有文件作用域。作用域:從定義變量位置到包含該定義的文件的結尾處。在其它位置使用該變量應用extern來聲明該變量。Page 38作用域與存儲類 2)存儲時期 靜態(tài)存儲時期:程序運行期間一直存在,給變量分配固定的存儲空間;所有全局變量具有靜態(tài)存儲時期(具有靜態(tài)存儲時期
12、的并不都是全局變量),但是修飾全局變量的關鍵詞static表明的是鏈接類型,并非存儲時期。 動態(tài)(自動)存儲時期:運行期間根據需要動態(tài)的給變量分配存儲空間。Page 39作用域與存儲類 3)5種存儲類存儲類存儲時期作用域鏈接聲明方式自動自動代碼塊空代碼塊內寄存器自動代碼塊空代碼塊內,使用關鍵字register外部靜態(tài)靜態(tài)文件外部所有函數之外內部靜態(tài)靜態(tài)文件內部所有函數之外,使用關鍵字static代碼塊靜態(tài)靜態(tài)代碼塊空代碼塊內,使用關鍵字staticPage 40C語言復習 1)循環(huán)與分支2)作用域與存儲類3)內存與指針)內存與指針4)位操作5)預編譯處理Page 41內存與指針 1)內存分配方
13、式 從靜態(tài)存儲區(qū)分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static變量; 從棧上創(chuàng)建。在執(zhí)行函數時,函數內局部變量的存儲單元都可以在棧上創(chuàng)建,函數執(zhí)行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限; 動態(tài)內存分配。程序在運行的時候由程序員自己負責申請和釋放內存。Page 42內存與指針 2)內存陷阱 C語言的靈活性,指針的應用,以及C語法的寬容性很容易造成代碼的錯誤,這其中最主要的就是內存單元的溢出。a) 堆棧溢出b) 數組越界. 將錯誤鎖定在一個函數中以后,首先應該關注內存的問題。Pag
14、e 43內存與指針 舉例,看看下面這段代碼有什么問題char *DoSomething()char i32*1024;.return i;兩個重大問題:兩個重大問題:1、臨時變量在堆棧上創(chuàng)建,太大的、臨時變量在堆棧上創(chuàng)建,太大的臨時變量數組會沖掉堆棧;臨時變量數組會沖掉堆棧;2、返回堆棧中的地址是沒有意義的,、返回堆棧中的地址是沒有意義的,因為堆棧中的內容永遠是不確定的。因為堆棧中的內容永遠是不確定的。Page 44內存與指針 數組越界的危險 臨時數組:在棧上創(chuàng)建,因此臨時數組越界有可能導致某些局部變量莫明其妙被改,函數返回時崩潰等等; 全局數組:在靜態(tài)存儲區(qū)創(chuàng)建,因此全局數據越界有可能導致某
15、些全局變量莫明其妙被改,被沖的動態(tài)內存無法釋放等等。Page 45內存與指針 3)指針 指針是什么?指針是一個變量,它的值是另外一個變量的地址。 指針的類型指針所指向的變量的類型,就是指針的類型。舉例,右邊的運算有何不同:int X2, *pX=&X0;pX+;char Y2,*pY=&Y0;pY+;Page 46內存與指針 指針的三要素 1、指針指向的地址;2、指針指向地址上的內容;3、指針本身的地址; 舉例:int A, *pA, *ppA;pA = &A;ppA = &pA;Page 47內存與指針 指針的大?。ㄖ羔樧兞空加玫膬却婵臻g) 舉例,以下為ARM
16、平臺下的一段32位C程序,請計算sizeof的值。char str = “Hello”;char *p = str;int n = 10;sizeof(str) = ?sizeof(p) = ?sizeof(n) = ?sizeof(str) = 6sizeof(p) = 4sizeof(n) = 4Page 48內存與指針 指針的初始化 指針變量在沒有被初始化之前,它的值是隨機的;一個指向不明的指針是非常危險的。 當創(chuàng)建一個指針時,系統(tǒng)只分配了用來存儲指針本身的內存空間,并不分配用來存儲數據的內存空間。使用指針之前,必須給它賦予一個已分配的內存地址。Page 49內存與指針 指針與數組舉例,
17、下列操作是否合法:int a4,*p;p = a;*(a+2) = 0 x00;p2 = 0 x01;/等價于p=&a0;/等價于a2;/等價于*(p+2);但是數組名不同于指針:數組名a是指向數組起始位置的“常量”。因此不能對數組名進行賦值操作。a = p;/錯誤a+;/錯誤Page 50內存與指針 指針與數組什么時候是相同的舉例,以下為ARM平臺下的一段32位C程序,請計算sizeof的值。void Func(char a100)sizeof(a) = ?sizeof(a) = 4(1)數組名作為函數形參時,在函數體內,其失去了本身的內涵,僅僅只是一個指針;(2)很遺憾,在失去其內
18、涵的同時,它還失去了其常量特性,可以作自增、自減等操作,可以被修改。Page 51內存與指針 數組與指針運用規(guī)則數組數組聲明聲明使用使用定義,如char a10不能寫成指針的形式extern,如extern char a不能寫成指針的形式func(char a);或func(char *a)函數參數可以寫成指針的形式c = ai;或c = *(a+i);可以寫成指針的形式Page 52C語言復習 1)循環(huán)與分支2)作用域與存儲類3)內存與指針4)位操作)位操作5)預編譯處理Page 53位操作 1)位操作的用途 硬件寄存器控制; 壓縮和加密操作; 提高程序運行效率; .因為位是程序可以操作的最
19、小數據單位,所以理論上可以用“位操作”完成所有的運算與操作。Page 54位操作 2)位運算符 位邏輯運算符& 位與(兩個數對應位都為1結果才為1)| 位或(兩個數對應位有一個為1結果則為1 ) 位異或(兩個數對應位不同結果則為1 ) 按位取反(單目運算符) 移位運算符 右移 Page 55位操作 3)用法:掩碼位操作符通常跟掩碼一起用。掩碼是某些位為開而某些位為關的位組合。例:flag &= MASK;00000 01010110 11000000010MASKflag&=Page 56位操作 4)用法:打開位、關閉位、轉置位 打開位:flag = flag | MA
20、SK;或flag |= MASK; 關閉位: flag = flag & MASK;或flag &= MASK; 轉置位: flag = flag MASK;或flag = MASK;Page 57位操作 5)用法:查看某一位的值 錯誤用法:if(flag = MASK) 正確用法:if(flag&MASK) = MASK)位運算符的優(yōu)先級低于=,因此需要在flag&MASK的兩側加上圓括號。Page 58位操作 6)用法:移位操作unsigned char ch=0 x07;/00000111unsigned char i;i = ch 2;00000 111
21、11000 00000000 001左移右移Page 59C語言復習 1)循環(huán)與分支2)作用域與存儲類3)內存與指針4)位操作5)預編譯處理)預編譯處理Page 60預編譯處理 C編譯系統(tǒng)在對程序進行編譯之前,先進行預處理。C提供的預處理功能主要有以下三種: 宏定義 文件包含 條件編譯Page 61預編譯處理 1)宏定義 類對象宏例:#define STX 0 x02 類函數宏例:#define SQUARE(x) (x)*(x) 幾點說明:a.宏定義不是C語句,不在行末加分號;b.宏名有效范圍為從定義處到本源文件結束;c.在宏定義時,可以引用已經定義的宏名;d.宏替換不占運行時間,只占編譯時
22、間;Page 62預編譯處理 2)文件包含:#include 預處理器發(fā)現#include后,就會尋找后跟的這個文件并把這個文件的內容復制到當前位置替換#include指令; 使用#include指令的一些例子:#include 從標準庫路徑開始搜索文件#include “def.h”從當前工作路徑開始搜索文件#include “/usr/head/def.h”搜索“/usr/head/”目錄Page 63預編譯處理 3)條件編譯 條件編譯指不對整個程序編譯,而是編譯滿足條件的那部分。條件編譯有以下幾種形式:a. #ifdef 標識符 程序段1; #else 程序段2; #endif它的作用:當標識符在前面已經定義過,則對程序段1進行編譯,否則對程序段2進行編譯。Page 64預編譯處理b. #ifndef 標識符程序段1;#else程序段2;#endif它的作用和#ifdef相反,當標識符之前沒被定
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 新能源出租車運營權承包經營合同
- 殘疾人職業(yè)培訓與就業(yè)保障協(xié)議
- 婚內財產協(xié)議模板
- 住院患者一般護理常規(guī)
- 智慧銀行信息化系統(tǒng)建設方案
- 手術室護理查房
- 在職教師普通話培訓提升計劃
- 企業(yè)激勵培訓
- 日本現代教育體系解析
- 正常產程常規(guī)培訓
- GB/T 2833-1996陶管彎曲強度試驗方法
- DB12T 1179-2023 泥態(tài)固化土道路填筑技術規(guī)程
- 西安市綠化養(yǎng)護管理標準
- 學校機房網絡規(guī)劃與設計
- 開標一覽表(模板)
- 建筑工程公司安全生產責任制度
- 2009-2022歷年河北省公安廳高速交警總隊招聘考試真題含答案帶詳解2022-2023上岸資料匯編3
- 湖北恩施州法院系統(tǒng)招考聘用雇員制審判輔助人員111名模擬卷含答案
- 被執(zhí)行人財產申報表
- 人教版五年級語文(下冊)期末試卷(附答案)
- 信用修復申請書
評論
0/150
提交評論