嵌入式系統(tǒng)C語(yǔ)言編程基礎(chǔ)幻燈片_第1頁(yè)
嵌入式系統(tǒng)C語(yǔ)言編程基礎(chǔ)幻燈片_第2頁(yè)
嵌入式系統(tǒng)C語(yǔ)言編程基礎(chǔ)幻燈片_第3頁(yè)
嵌入式系統(tǒng)C語(yǔ)言編程基礎(chǔ)幻燈片_第4頁(yè)
嵌入式系統(tǒng)C語(yǔ)言編程基礎(chǔ)幻燈片_第5頁(yè)
已閱讀5頁(yè),還剩76頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、嵌入式系統(tǒng)C語(yǔ)言編程基礎(chǔ),楊高波,SNBC,P,目錄,關(guān)于本課程 C語(yǔ)言復(fù)習(xí) 編程規(guī)范 開發(fā)高效程序的技巧,P,為什么學(xué)習(xí)本課程,會(huì)C語(yǔ)法與會(huì)用C語(yǔ)言寫程序是兩個(gè)概念 C的靈活性以及由此而產(chǎn)生的陷阱非常多 The Most Beautiful Language and Most Dangerous Language in the Programming World! 本課程將嵌入式系統(tǒng)中最基本的(最經(jīng)常用到的)概念與技巧介紹給大家,P,小測(cè)驗(yàn)?,P,Quiz 1,所有嵌入式系統(tǒng)的主流程最后都進(jìn)入一個(gè)死循環(huán),怎樣用C語(yǔ)言實(shí)現(xiàn)一個(gè)死循環(huán)?,P,Quiz 2,while().和do.while()有

2、什么區(qū)別?,P,Quiz 3,用變量a給出下列定義: 一個(gè)整型數(shù) 一個(gè)指向整型數(shù)的指針 一個(gè)有10個(gè)整型數(shù)的的數(shù)組 一個(gè)有10個(gè)指針的數(shù)組,該指針是指向一個(gè)整型數(shù)的,P,Quiz 4,關(guān)鍵字static的作用是什么?,P,Quiz 5,關(guān)鍵字const的作用是什么?,P,Quiz 6,定義一個(gè)標(biāo)準(zhǔn)宏MIN ,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)。,P,Quiz 7,嵌入式系統(tǒng)中經(jīng)常要對(duì)變量或寄存器進(jìn)行位操作。給定一個(gè)int型變量a,寫兩段代碼,第一個(gè)將a的bit 3置為1,第二個(gè)將a的bit 3置為0。以上兩個(gè)操作中,要保持其它位不變。,P,Quiz 8,嵌入式系統(tǒng)具有經(jīng)常去直接訪問物理地址的特

3、點(diǎn)。在某工程中,要求設(shè)置一絕對(duì)地址為0 x5a00 的整型變量的值為0 xaa55。寫代碼去完成這一任務(wù)。,P,Quiz 9,下面這段代碼的輸出是什么?void foo(void)unsigned int a = 6;int b = -20;(a+b 6) ? puts(6) : puts(6);,P,Quiz 10,請(qǐng)?jiān)u論下面一段程序代碼:void test()char string10;char *str = “0123456789”;strcpy(string,str);,P,Quiz 11,請(qǐng)?jiān)u論下面一段程序代碼:void GetMemory(char *p)p = (char *)m

4、alloc(0 x20);void Test(void)char *str = NULL;GetMemory(str);strcpy(str,”Hello World!”);printf(str);,P,Quiz 12,中斷是嵌入式系統(tǒng)的重要組成部分。請(qǐng)?jiān)u論下面一段中斷服務(wù)子程序代碼:_interrupt double compute_area (double radius)double area = PI * radius * radius;printf(nArea = %f, area);return area;,P,Answer!,P,Quiz 1 Answer,while(1).,P,

5、Quiz 2 Answer,while().為入口條件循環(huán),即在每次執(zhí)行循環(huán)之前先檢查判斷條件;do.while()為退出條件循環(huán),即在執(zhí)行循環(huán)之后再檢查判斷條件。,P,Quiz 3 Answer,a) int a;b) int *a;c) int a10;d) int *a10;,P,Quiz 4 Answer,在C 語(yǔ)言中,關(guān)鍵字static 有三個(gè)明顯的作用:1) 在函數(shù)體內(nèi),一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。2) 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個(gè)本地的全局變量。3) 在模塊內(nèi),一個(gè)被聲

6、明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。,P,Quiz 5 Answer,const是constant的縮寫,“恒定不變”的意思。被const修飾的東西都受到強(qiáng)制保護(hù),可以預(yù)防意外的變動(dòng),能提高程序的健壯性。 const常量與#define常量:前者有數(shù)據(jù)類型,后者只是字符替換(而且可能產(chǎn)生意料不到的錯(cuò)誤),所以編譯器可以對(duì)前者進(jìn)行安全性檢查。,P,Quiz 6 Answer,#define MIN(A,B) (A) = (B) ? (A) : (B) #define宏的副作用,下面的代碼執(zhí)行后會(huì)發(fā)生什么事:least = MIN(*

7、p+, b);,P,Quiz 7 Answer,const int BIT3 = 0 x013;static int a;void SetBit3(void)a |= BIT3;void ClearBit3(void)a ,P,Quiz 8 Answer,int *ptTemp = (int *)0 x5a00;*ptTemp = 0 xaa55;,P,Quiz 9 Answer,輸出為“6”,原因是當(dāng)表達(dá)式中存在有符號(hào)類型和無(wú)符號(hào)類型時(shí)所有的操作數(shù)都自動(dòng)轉(zhuǎn)換為無(wú)符號(hào)類型。 因此-20 變成了一個(gè)非常大的正整數(shù),所以該表達(dá)式計(jì)算出的結(jié)果大于6。這一點(diǎn)對(duì)于頻繁用到無(wú)符號(hào)數(shù)據(jù)類型的嵌入式系統(tǒng)來(lái)說(shuō)是

8、豐常重要的。,P,Quiz 10 Answer,字符串str需要11個(gè)字節(jié)才能存放下(包括末尾的0),而string只有10個(gè)字節(jié)的空間,所以strcpy會(huì)導(dǎo)致數(shù)組越界。,P,Quiz 11 Answer,編譯器總是要為函數(shù)的每個(gè)參數(shù)制作臨時(shí)副本,指針參數(shù)p的副本是_p,編譯器使 _p = p。本例中,_p申請(qǐng)了新的內(nèi)存,但只是_p的值改變了,p的值卻絲毫未變,仍然為NULL。事實(shí)上,每執(zhí)行一次GetMemory就會(huì)泄漏一塊內(nèi)存。,P,Quiz 12 Answer,1)ISR不能返回值;2)不能向ISR傳遞參數(shù);3)ISR應(yīng)該是短而有效率的,因而在ISR中做浮點(diǎn)運(yùn)算、使用printf等是不明智

9、的,會(huì)經(jīng)常有重入和性能上的問題。,P,還是先復(fù)習(xí)一下C吧!,P,C語(yǔ)言復(fù)習(xí),1)循環(huán)與分支2)作用域與存儲(chǔ)類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理,P,循環(huán)與分支,1)幾種循環(huán)語(yǔ)句:for(initialize;test;update)body;while(test)body;dobody;while(test); 2)循環(huán)輔助手段:break語(yǔ)句用于跳出循環(huán),continue語(yǔ)句用于結(jié)束本次循環(huán)。,P,循環(huán)與分支,3)三種形式的if語(yǔ)句:if(expression).if(expression).else.if(expression1).else if(expression).else.,P

10、,循環(huán)與分支,4)條件運(yùn)算符?: expression1 ? expression2 : expression3 如果expression1為真,整個(gè)表達(dá)式的值為expression2的值,否則為expression3的值; 是if.else.的簡(jiǎn)寫形式,但是編譯器可以產(chǎn)生比if.else.更優(yōu)化的代碼。,P,循環(huán)與分支,5)多重選擇:switchswitch(expression)case constant1: statements; break;case constant2: statements; break;.default: statements; break;switch判斷表達(dá)式

11、必須具有整數(shù)值,case標(biāo)簽必須是整數(shù)常量或整數(shù)常量表達(dá)式。,P,C語(yǔ)言復(fù)習(xí),1)循環(huán)與分支2)作用域與存儲(chǔ)類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理,P,作用域與存儲(chǔ)類,1)作用域 代碼塊作用域(局部變量)代碼塊:包含在開始花括號(hào)和對(duì)應(yīng)結(jié)束花括號(hào)之內(nèi)的一段代碼。作用域:從定義變量位置到該代碼塊的末尾。 文件作用域(全局變量)在所有函數(shù)之外定義的變量具有文件作用域。作用域:從定義變量位置到包含該定義的文件的結(jié)尾處。在其它位置使用該變量應(yīng)用extern來(lái)聲明該變量。,P,作用域與存儲(chǔ)類,2)存儲(chǔ)時(shí)期 靜態(tài)存儲(chǔ)時(shí)期:程序運(yùn)行期間一直存在,給變量分配固定的存儲(chǔ)空間;所有全局變量具有靜態(tài)存儲(chǔ)時(shí)期(具有靜

12、態(tài)存儲(chǔ)時(shí)期的并不都是全局變量),但是修飾全局變量的關(guān)鍵詞static表明的是鏈接類型,并非存儲(chǔ)時(shí)期。 動(dòng)態(tài)(自動(dòng))存儲(chǔ)時(shí)期:運(yùn)行期間根據(jù)需要?jiǎng)討B(tài)的給變量分配存儲(chǔ)空間。,P,作用域與存儲(chǔ)類,3)5種存儲(chǔ)類,P,C語(yǔ)言復(fù)習(xí),1)循環(huán)與分支2)作用域與存儲(chǔ)類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理,P,內(nèi)存與指針,1)內(nèi)存分配方式 從靜態(tài)存儲(chǔ)區(qū)分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。例如全局變量,static變量; 從棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高

13、,但是分配的內(nèi)存容量有限; 動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候由程序員自己負(fù)責(zé)申請(qǐng)和釋放內(nèi)存。,P,內(nèi)存與指針,2)內(nèi)存陷阱 C語(yǔ)言的靈活性,指針的應(yīng)用,以及C語(yǔ)法的寬容性很容易造成代碼的錯(cuò)誤,這其中最主要的就是內(nèi)存單元的溢出。a) 堆棧溢出b) 數(shù)組越界. 將錯(cuò)誤鎖定在一個(gè)函數(shù)中以后,首先應(yīng)該關(guān)注內(nèi)存的問題。,P,內(nèi)存與指針,舉例,看看下面這段代碼有什么問題char *DoSomething()char i32*1024;.return i;,兩個(gè)重大問題:1、臨時(shí)變量在堆棧上創(chuàng)建,太大的臨時(shí)變量數(shù)組會(huì)沖掉堆棧;2、返回堆棧中的地址是沒有意義的,因?yàn)槎褩V械膬?nèi)容永遠(yuǎn)是不確定的。,P,內(nèi)存與指針,

14、數(shù)組越界的危險(xiǎn) 臨時(shí)數(shù)組:在棧上創(chuàng)建,因此臨時(shí)數(shù)組越界有可能導(dǎo)致某些局部變量莫明其妙被改,函數(shù)返回時(shí)崩潰等等; 全局?jǐn)?shù)組:在靜態(tài)存儲(chǔ)區(qū)創(chuàng)建,因此全局?jǐn)?shù)據(jù)越界有可能導(dǎo)致某些全局變量莫明其妙被改,被沖的動(dòng)態(tài)內(nèi)存無(wú)法釋放等等。,P,內(nèi)存與指針,3)指針 指針是什么?指針是一個(gè)變量,它的值是另外一個(gè)變量的地址。 指針的類型指針?biāo)赶虻淖兞康念愋?,就是指針的類型。舉例,右邊的運(yùn)算有何不同:int X2, *pX=,P,內(nèi)存與指針,指針的三要素 1、指針指向的地址;2、指針指向地址上的內(nèi)容;3、指針本身的地址; 舉例:int A, *pA, *ppA;pA = ,P,內(nèi)存與指針,指針的大?。ㄖ羔樧兞空加玫?/p>

15、內(nèi)存空間) 舉例,以下為ARM平臺(tái)下的一段32位C程序,請(qǐng)計(jì)算sizeof的值。char str = “Hello”;char *p = str;int n = 10;sizeof(str) = ?sizeof(p) = ?sizeof(n) = ?,sizeof(str) = 6sizeof(p) = 4sizeof(n) = 4,P,內(nèi)存與指針,指針的初始化 指針變量在沒有被初始化之前,它的值是隨機(jī)的;一個(gè)指向不明的指針是非常危險(xiǎn)的。 當(dāng)創(chuàng)建一個(gè)指針時(shí),系統(tǒng)只分配了用來(lái)存儲(chǔ)指針本身的內(nèi)存空間,并不分配用來(lái)存儲(chǔ)數(shù)據(jù)的內(nèi)存空間。使用指針之前,必須給它賦予一個(gè)已分配的內(nèi)存地址。,P,內(nèi)存與指針,

16、指針與數(shù)組舉例,下列操作是否合法:int a4,*p;p = a;*(a+2) = 0 x00;p2 = 0 x01;,/等價(jià)于p=/錯(cuò)誤a+;/錯(cuò)誤,P,內(nèi)存與指針,指針與數(shù)組什么時(shí)候是相同的舉例,以下為ARM平臺(tái)下的一段32位C程序,請(qǐng)計(jì)算sizeof的值。void Func(char a100)sizeof(a) = ?,sizeof(a) = 4,(1)數(shù)組名作為函數(shù)形參時(shí),在函數(shù)體內(nèi),其失去了本身的內(nèi)涵,僅僅只是一個(gè)指針;(2)很遺憾,在失去其內(nèi)涵的同時(shí),它還失去了其常量特性,可以作自增、自減等操作,可以被修改。,P,內(nèi)存與指針,數(shù)組與指針運(yùn)用規(guī)則,數(shù)組,聲明,使用,定義,如char

17、 a10不能寫成指針的形式,extern,如extern char a不能寫成指針的形式,func(char a);或func(char *a)函數(shù)參數(shù)可以寫成指針的形式,c = ai;或c = *(a+i);可以寫成指針的形式,P,C語(yǔ)言復(fù)習(xí),1)循環(huán)與分支2)作用域與存儲(chǔ)類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理,P,位操作,1)位操作的用途 硬件寄存器控制; 壓縮和加密操作; 提高程序運(yùn)行效率; .,因?yàn)槲皇浅绦蚩梢圆僮鞯淖钚?shù)據(jù)單位,所以理論上可以用“位操作”完成所有的運(yùn)算與操作。,P,位操作,2)位運(yùn)算符 位邏輯運(yùn)算符或flag |= MASK; 關(guān)閉位: flag = flag ,P

18、,位操作,5)用法:查看某一位的值 錯(cuò)誤用法:if(flag = MASK) 正確用法:if(flag/00000111 unsigned char i; i = ch 2;,左移,右移,P,C語(yǔ)言復(fù)習(xí),1)循環(huán)與分支2)作用域與存儲(chǔ)類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理,P,預(yù)編譯處理,C編譯系統(tǒng)在對(duì)程序進(jìn)行編譯之前,先進(jìn)行預(yù)處理。C提供的預(yù)處理功能主要有以下三種: 宏定義 文件包含 條件編譯,P,預(yù)編譯處理,1)宏定義 類對(duì)象宏例:#define STX 0 x02 類函數(shù)宏例:#define SQUARE(x) (x)*(x) 幾點(diǎn)說(shuō)明:a.宏定義不是C語(yǔ)句,不在行末加分號(hào);b.宏名有

19、效范圍為從定義處到本源文件結(jié)束;c.在宏定義時(shí),可以引用已經(jīng)定義的宏名;d.宏替換不占運(yùn)行時(shí)間,只占編譯時(shí)間;,P,預(yù)編譯處理,2)文件包含:#include 預(yù)處理器發(fā)現(xiàn)#include后,就會(huì)尋找后跟的這個(gè)文件并把這個(gè)文件的內(nèi)容復(fù)制到當(dāng)前位置替換#include指令; 使用#include指令的一些例子:,P,預(yù)編譯處理,3)條件編譯 條件編譯指不對(duì)整個(gè)程序編譯,而是編譯滿足條件的那部分。條件編譯有以下幾種形式:a. #ifdef 標(biāo)識(shí)符 程序段1; #else 程序段2; #endif它的作用:當(dāng)標(biāo)識(shí)符在前面已經(jīng)定義過,則對(duì)程序段1進(jìn)行編譯,否則對(duì)程序段2進(jìn)行編譯。,P,預(yù)編譯處理,b.

20、 #ifndef 標(biāo)識(shí)符程序段1;#else程序段2;#endif它的作用和#ifdef相反,當(dāng)標(biāo)識(shí)符之前沒被定義過,則對(duì)程序段1進(jìn)行編譯,否則就對(duì)程序段2進(jìn)行編譯。,P,預(yù)編譯處理,c. #if 表達(dá)式程序段1;#else程序段2;#endif它的作用:當(dāng)表達(dá)式的值為真時(shí),對(duì)程序段1進(jìn)行編譯,都則就對(duì)程序段2進(jìn)行編譯;,P,預(yù)編譯處理,舉例,下面是某工程中.h文件中的一段程序,請(qǐng)說(shuō)明#ifndef/#define/#endif結(jié)構(gòu)的作用。#ifndefDEF_H#defineDEF_H#include #include“graphics.h”.#endif,防止頭文件被重復(fù)引用,P,編程規(guī)范

21、,P,編程規(guī)范,1)規(guī)范的作用 改善代碼質(zhì)量 提高開發(fā)速度 增進(jìn)團(tuán)隊(duì)精神 養(yǎng)成良好習(xí)慣,P,編程規(guī)范,2)編程規(guī)范 養(yǎng)成良好的編程習(xí)慣,P,開發(fā)高效程序的技巧,P,開發(fā)高效程序的技巧,1)ARM編程中局部變量的使用 舉例,請(qǐng)看一面一段程序:int checksum(int *data) char i; . for(i=0;i64;i+).; .,.ADDr1,r1,#1ANDr1,r1,#0 xFFCMPr1,#0 x40.,P,開發(fā)高效程序的技巧,把上面的程序段將i聲明為unsigned int類型,比較一下:,.ADDr1,r1,#1CMPr1,#0 x40.,ARM編程中局部變量類型的使

22、用:char或short類型并不比int類型占用更小的寄存器空間或者堆??臻g,應(yīng)盡量不要使用char或short作為局部變量,以防止做不必要的轉(zhuǎn)換;除非要使用char或short的溢出歸零特性,如255+1=0。,P,開發(fā)高效程序的技巧,2)ARM編程中函數(shù)參數(shù)的傳遞 4寄存器原則(four-register rule):ARM-Thumb過程調(diào)用標(biāo)準(zhǔn)(ATPCS)定義了R0-R3四個(gè)寄存器作為參數(shù)傳遞和結(jié)果返回寄存器,如果參數(shù)超過4個(gè),則使用堆棧進(jìn)行傳遞(額外的指令和慢速的存儲(chǔ)器操作)。因?yàn)閮?nèi)部寄存器的訪問速度要遠(yuǎn)遠(yuǎn)大于存儲(chǔ)器,所以我們應(yīng)盡量把函數(shù)的參數(shù)控制在4個(gè)以下。,P,開發(fā)高效程序的技

23、巧,r3r2r1r0,sp+8sp+4sp,圖: ATPCS參數(shù)傳遞,P,開發(fā)高效程序的技巧,3)結(jié)構(gòu)體安排 舉例,對(duì)下面兩個(gè)結(jié)構(gòu)體進(jìn)行比較struct A char a; int b; char c; short d;struct B char a; char c; short d; int b;,P,開發(fā)高效程序的技巧,4)C語(yǔ)言中的封裝思想 舉例,給出這樣一個(gè)人機(jī)界面:,打印速度 100 ,液晶顯示屏,按鍵,要求:以中間的按鍵切換液晶顯示菜單,左右兩個(gè)按鍵對(duì)當(dāng)前項(xiàng)的值進(jìn)行增減操作。,P,開發(fā)高效程序的技巧,我曾經(jīng)這樣做:void onLeftKey() switch(currentFocus) case MENU1: menu1onLeft(); break; case MENU2: menu2onLeft(); break; . ,void onMidKey() currentFocus+; switch(currentFocus) case MENU1: MenuText =

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論