




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、嵌入式系統(tǒng)C語言編程基礎(chǔ)楊高波SNBCPage 2目錄 關(guān)于本課程 C語言復(fù)習(xí) 編程規(guī)范 開發(fā)高效程序的技巧Page 3為什么學(xué)習(xí)本課程 會C語法與會用C語言寫程序是兩個概念 C的靈活性以及由此而產(chǎn)生的陷阱非常多 The Most Beautiful Language and Most Dangerous Language in the Programming World! 本課程將嵌入式系統(tǒng)中最基本的(最經(jīng)常用到的)概念與技巧介紹給大家Page 4小測驗?Page 5Quiz 1 所有嵌入式系統(tǒng)的主流程最后都進(jìn)入一個死循環(huán),怎樣用C語言實現(xiàn)一個死循環(huán)?Page 6Quiz 2 while()
2、.和do.while()有什么區(qū)別?Page 7Quiz 3用變量a給出下列定義:a) 一個整型數(shù)b) 一個指向整型數(shù)的指針c) 一個有10個整型數(shù)的的數(shù)組d) 一個有10個指針的數(shù)組,該指針是指向一個整型數(shù)的Page 8Quiz 4 關(guān)鍵字static的作用是什么?Page 9Quiz 5 關(guān)鍵字const的作用是什么?Page 10Quiz 6 定義一個標(biāo)準(zhǔn)宏MIN ,這個宏輸入兩個參數(shù)并返回較小的一個。Page 11Quiz 7 嵌入式系統(tǒng)中經(jīng)常要對變量或寄存器進(jìn)行位操作。給定一個int型變量a,寫兩段代碼,第一個將a的bit 3置為1,第二個將a的bit 3置為0。以上兩個操作中,要保
3、持其它位不變。Page 12Quiz 8 嵌入式系統(tǒng)具有經(jīng)常去直接訪問物理地址的特點。在某工程中,要求設(shè)置一絕對地址為0 x5a00 的整型變量的值為0 xaa55。寫代碼去完成這一任務(wù)。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)的重要組成部分。請評論下面一段中斷服務(wù)子程序代碼:_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 語言中,關(guān)鍵字static 有三個明顯的作用:1) 在函數(shù)體內(nèi),一個被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。2
6、) 在模塊內(nèi)(但在函數(shù)體外),一個被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個本地的全局變量。3) 在模塊內(nèi),一個被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。Page 22Quiz 5 Answer const是constant的縮寫,“恒定不變”的意思。被const修飾的東西都受到強(qiáng)制保護(hù),可以預(yù)防意外的變動,能提高程序的健壯性。 const常量與#define常量:前者有數(shù)據(jù)類型,后者只是字符替換(而且可能產(chǎn)生意料不到的錯誤),所以編譯器可以對前者進(jìn)行安全性檢查。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”,原因是當(dāng)表達(dá)式中存在有符號類型和無符號類型時所有的操作數(shù)都自動轉(zhuǎn)換為無符號類型。 因此-20 變成了一個非常大的正整數(shù),所以該表達(dá)式計算出的結(jié)果大于6。這一點對于頻繁用到無符號數(shù)據(jù)類型的嵌入式系統(tǒng)來說是豐常重要的。Page 27Quiz 10 Answer 字符串str需要11個字節(jié)才能存放下(包括末尾的0),而strin
8、g只有10個字節(jié)的空間,所以strcpy會導(dǎo)致數(shù)組越界。 Page 28Quiz 11 Answer 編譯器總是要為函數(shù)的每個參數(shù)制作臨時副本,指針參數(shù)p的副本是_p,編譯器使 _p = p。本例中,_p申請了新的內(nèi)存,但只是_p的值改變了,p的值卻絲毫未變,仍然為NULL。事實上,每執(zhí)行一次GetMemory就會泄漏一塊內(nèi)存。Page 29Quiz 12 Answer 1)ISR不能返回值;2)不能向ISR傳遞參數(shù);3)ISR應(yīng)該是短而有效率的,因而在ISR中做浮點運(yùn)算、使用printf等是不明智的,會經(jīng)常有重入和性能上的問題。Page 30還是先復(fù)習(xí)一下C吧!Page 31C語言復(fù)習(xí) 1)
9、循環(huán)與分支2)作用域與存儲類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理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語句用于結(jié)束本次循環(huán)。Page 33循環(huán)與分支 3)三種形式的if語句:if(expression).if(expression).else.if(expression1).else if(expression).else.Page 34循環(huán)與分支 4)條件運(yùn)算符?:expression1
10、? expression2 : expression3 如果expression1為真,整個表達(dá)式的值為expression2的值,否則為expression3的值; 是if.else.的簡寫形式,但是編譯器可以產(chǎn)生比if.else.更優(yōu)化的代碼。Page 35循環(huán)與分支 5)多重選擇:switchswitch(expression)case constant1: statements; break;case constant2: statements; break;.default: statements; break;switch判斷表達(dá)式必須具有整數(shù)值,case標(biāo)簽必須是整數(shù)常量或整數(shù)常
11、量表達(dá)式。Page 36C語言復(fù)習(xí) 1)循環(huán)與分支2)作用域與存儲類)作用域與存儲類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理Page 37作用域與存儲類 1)作用域 代碼塊作用域(局部變量)代碼塊:包含在開始花括號和對應(yīng)結(jié)束花括號之內(nèi)的一段代碼。作用域:從定義變量位置到該代碼塊的末尾。 文件作用域(全局變量)在所有函數(shù)之外定義的變量具有文件作用域。作用域:從定義變量位置到包含該定義的文件的結(jié)尾處。在其它位置使用該變量應(yīng)用extern來聲明該變量。Page 38作用域與存儲類 2)存儲時期 靜態(tài)存儲時期:程序運(yùn)行期間一直存在,給變量分配固定的存儲空間;所有全局變量具有靜態(tài)存儲時期(具有靜態(tài)存儲時期
12、的并不都是全局變量),但是修飾全局變量的關(guān)鍵詞static表明的是鏈接類型,并非存儲時期。 動態(tài)(自動)存儲時期:運(yùn)行期間根據(jù)需要動態(tài)的給變量分配存儲空間。Page 39作用域與存儲類 3)5種存儲類存儲類存儲時期作用域鏈接聲明方式自動自動代碼塊空代碼塊內(nèi)寄存器自動代碼塊空代碼塊內(nèi),使用關(guān)鍵字register外部靜態(tài)靜態(tài)文件外部所有函數(shù)之外內(nèi)部靜態(tài)靜態(tài)文件內(nèi)部所有函數(shù)之外,使用關(guān)鍵字static代碼塊靜態(tài)靜態(tài)代碼塊空代碼塊內(nèi),使用關(guān)鍵字staticPage 40C語言復(fù)習(xí) 1)循環(huán)與分支2)作用域與存儲類3)內(nèi)存與指針)內(nèi)存與指針4)位操作5)預(yù)編譯處理Page 41內(nèi)存與指針 1)內(nèi)存分配方
13、式 從靜態(tài)存儲區(qū)分配。內(nèi)存在程序編譯的時候就已經(jīng)分配好,這塊內(nèi)存在程序的整個運(yùn)行期間都存在。例如全局變量,static變量; 從棧上創(chuàng)建。在執(zhí)行函數(shù)時,函數(shù)內(nèi)局部變量的存儲單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時這些存儲單元自動被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限; 動態(tài)內(nèi)存分配。程序在運(yùn)行的時候由程序員自己負(fù)責(zé)申請和釋放內(nèi)存。Page 42內(nèi)存與指針 2)內(nèi)存陷阱 C語言的靈活性,指針的應(yīng)用,以及C語法的寬容性很容易造成代碼的錯誤,這其中最主要的就是內(nèi)存單元的溢出。a) 堆棧溢出b) 數(shù)組越界. 將錯誤鎖定在一個函數(shù)中以后,首先應(yīng)該關(guān)注內(nèi)存的問題。Pag
14、e 43內(nèi)存與指針 舉例,看看下面這段代碼有什么問題char *DoSomething()char i32*1024;.return i;兩個重大問題:兩個重大問題:1、臨時變量在堆棧上創(chuàng)建,太大的、臨時變量在堆棧上創(chuàng)建,太大的臨時變量數(shù)組會沖掉堆棧;臨時變量數(shù)組會沖掉堆棧;2、返回堆棧中的地址是沒有意義的,、返回堆棧中的地址是沒有意義的,因為堆棧中的內(nèi)容永遠(yuǎn)是不確定的。因為堆棧中的內(nèi)容永遠(yuǎn)是不確定的。Page 44內(nèi)存與指針 數(shù)組越界的危險 臨時數(shù)組:在棧上創(chuàng)建,因此臨時數(shù)組越界有可能導(dǎo)致某些局部變量莫明其妙被改,函數(shù)返回時崩潰等等; 全局?jǐn)?shù)組:在靜態(tài)存儲區(qū)創(chuàng)建,因此全局?jǐn)?shù)據(jù)越界有可能導(dǎo)致某
15、些全局變量莫明其妙被改,被沖的動態(tài)內(nèi)存無法釋放等等。Page 45內(nèi)存與指針 3)指針 指針是什么?指針是一個變量,它的值是另外一個變量的地址。 指針的類型指針?biāo)赶虻淖兞康念愋?,就是指針的類型。舉例,右邊的運(yùn)算有何不同:int X2, *pX=&X0;pX+;char Y2,*pY=&Y0;pY+;Page 46內(nèi)存與指針 指針的三要素 1、指針指向的地址;2、指針指向地址上的內(nèi)容;3、指針本身的地址; 舉例:int A, *pA, *ppA;pA = &A;ppA = &pA;Page 47內(nèi)存與指針 指針的大?。ㄖ羔樧兞空加玫膬?nèi)存空間) 舉例,以下為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內(nèi)存與指針 指針的初始化 指針變量在沒有被初始化之前,它的值是隨機(jī)的;一個指向不明的指針是非常危險的。 當(dāng)創(chuàng)建一個指針時,系統(tǒng)只分配了用來存儲指針本身的內(nèi)存空間,并不分配用來存儲數(shù)據(jù)的內(nèi)存空間。使用指針之前,必須給它賦予一個已分配的內(nèi)存地址。Page 49內(nèi)存與指針 指針與數(shù)組舉例,
17、下列操作是否合法:int a4,*p;p = a;*(a+2) = 0 x00;p2 = 0 x01;/等價于p=&a0;/等價于a2;/等價于*(p+2);但是數(shù)組名不同于指針:數(shù)組名a是指向數(shù)組起始位置的“常量”。因此不能對數(shù)組名進(jìn)行賦值操作。a = p;/錯誤a+;/錯誤Page 50內(nèi)存與指針 指針與數(shù)組什么時候是相同的舉例,以下為ARM平臺下的一段32位C程序,請計算sizeof的值。void Func(char a100)sizeof(a) = ?sizeof(a) = 4(1)數(shù)組名作為函數(shù)形參時,在函數(shù)體內(nèi),其失去了本身的內(nèi)涵,僅僅只是一個指針;(2)很遺憾,在失去其內(nèi)
18、涵的同時,它還失去了其常量特性,可以作自增、自減等操作,可以被修改。Page 51內(nèi)存與指針 數(shù)組與指針運(yùn)用規(guī)則數(shù)組數(shù)組聲明聲明使用使用定義,如char a10不能寫成指針的形式extern,如extern char a不能寫成指針的形式func(char a);或func(char *a)函數(shù)參數(shù)可以寫成指針的形式c = ai;或c = *(a+i);可以寫成指針的形式Page 52C語言復(fù)習(xí) 1)循環(huán)與分支2)作用域與存儲類3)內(nèi)存與指針4)位操作)位操作5)預(yù)編譯處理Page 53位操作 1)位操作的用途 硬件寄存器控制; 壓縮和加密操作; 提高程序運(yùn)行效率; .因為位是程序可以操作的最
19、小數(shù)據(jù)單位,所以理論上可以用“位操作”完成所有的運(yùn)算與操作。Page 54位操作 2)位運(yùn)算符 位邏輯運(yùn)算符& 位與(兩個數(shù)對應(yīng)位都為1結(jié)果才為1)| 位或(兩個數(shù)對應(yīng)位有一個為1結(jié)果則為1 ) 位異或(兩個數(shù)對應(yīng)位不同結(jié)果則為1 ) 按位取反(單目運(yùn)算符) 移位運(yùn)算符 右移 Page 55位操作 3)用法:掩碼位操作符通常跟掩碼一起用。掩碼是某些位為開而某些位為關(guān)的位組合。例:flag &= MASK;00000 01010110 11000000010MASKflag&=Page 56位操作 4)用法:打開位、關(guān)閉位、轉(zhuǎn)置位 打開位:flag = flag | MA
20、SK;或flag |= MASK; 關(guān)閉位: flag = flag & MASK;或flag &= MASK; 轉(zhuǎn)置位: flag = flag MASK;或flag = MASK;Page 57位操作 5)用法:查看某一位的值 錯誤用法:if(flag = MASK) 正確用法:if(flag&MASK) = MASK)位運(yùn)算符的優(yōu)先級低于=,因此需要在flag&MASK的兩側(cè)加上圓括號。Page 58位操作 6)用法:移位操作unsigned char ch=0 x07;/00000111unsigned char i;i = ch 2;00000 111
21、11000 00000000 001左移右移Page 59C語言復(fù)習(xí) 1)循環(huán)與分支2)作用域與存儲類3)內(nèi)存與指針4)位操作5)預(yù)編譯處理)預(yù)編譯處理Page 60預(yù)編譯處理 C編譯系統(tǒng)在對程序進(jìn)行編譯之前,先進(jìn)行預(yù)處理。C提供的預(yù)處理功能主要有以下三種: 宏定義 文件包含 條件編譯Page 61預(yù)編譯處理 1)宏定義 類對象宏例:#define STX 0 x02 類函數(shù)宏例:#define SQUARE(x) (x)*(x) 幾點說明:a.宏定義不是C語句,不在行末加分號;b.宏名有效范圍為從定義處到本源文件結(jié)束;c.在宏定義時,可以引用已經(jīng)定義的宏名;d.宏替換不占運(yùn)行時間,只占編譯時
22、間;Page 62預(yù)編譯處理 2)文件包含:#include 預(yù)處理器發(fā)現(xiàn)#include后,就會尋找后跟的這個文件并把這個文件的內(nèi)容復(fù)制到當(dāng)前位置替換#include指令; 使用#include指令的一些例子:#include 從標(biāo)準(zhǔn)庫路徑開始搜索文件#include “def.h”從當(dāng)前工作路徑開始搜索文件#include “/usr/head/def.h”搜索“/usr/head/”目錄Page 63預(yù)編譯處理 3)條件編譯 條件編譯指不對整個程序編譯,而是編譯滿足條件的那部分。條件編譯有以下幾種形式:a. #ifdef 標(biāo)識符 程序段1; #else 程序段2; #endif它的作用:當(dāng)標(biāo)識符在前面已經(jīng)定義過,則對程序段1進(jìn)行編譯,否則對程序段2進(jìn)行編譯。Page 64預(yù)編譯處理b. #ifndef 標(biāo)識符程序段1;#else程序段2;#endif它的作用和#ifdef相反,當(dāng)標(biāo)識符之前沒被定
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 上電院工程流體力學(xué)課件第1章 流體及其物理性質(zhì)
- 大五人格在醫(yī)療改革政策執(zhí)行中的作用研究
- 四川長江職業(yè)學(xué)院《樂理與視唱二》2023-2024學(xué)年第二學(xué)期期末試卷
- 鹽城幼兒師范高等專科學(xué)?!镀髽I(yè)項目施工實踐》2023-2024學(xué)年第二學(xué)期期末試卷
- 山東電子職業(yè)技術(shù)學(xué)院《心理統(tǒng)計學(xué)(上)》2023-2024學(xué)年第二學(xué)期期末試卷
- 長沙理工大學(xué)城南學(xué)院《和聲基礎(chǔ)理論》2023-2024學(xué)年第二學(xué)期期末試卷
- 武漢光谷職業(yè)學(xué)院《光通信原理》2023-2024學(xué)年第二學(xué)期期末試卷
- 智慧教育環(huán)境下學(xué)生的學(xué)習(xí)效果研究
- 2024年度河南省護(hù)師類之社區(qū)護(hù)理主管護(hù)師能力提升試卷A卷附答案
- 《舞蹈基礎(chǔ)與幼兒舞蹈(一)》課件-幼兒舞蹈基本步伐
- 客服投訴處理技巧培訓(xùn)
- 護(hù)理心理學(xué)試題及答案解讀
- 殯葬火化師試題及答案大全
- 2025年高考物理壓軸題專項訓(xùn)練:動量定理及碰撞類動量守恒定律的應(yīng)用(解析版)
- 2025年西藥藥劑員(中級)職業(yè)技能鑒定考試題庫(含答案)
- 5.2做自強(qiáng)不息的中國人(教學(xué)設(shè)計)2024-2025學(xué)年七年級道德與法治下冊(統(tǒng)編版2024)
- 《微信公眾號如何申請》課件
- 2024年CAD工程師認(rèn)證考試的題型解析試題及答案
- 2025年北方華創(chuàng)工作人員招聘考試筆試試題
- 2025 年中職高考對口升學(xué)(幼兒教育學(xué))真題試卷附參考答案
- 2025承諾合同(個人承諾)
評論
0/150
提交評論