嵌入式系統(tǒng)程序設(shè)計(jì)課件_第1頁(yè)
嵌入式系統(tǒng)程序設(shè)計(jì)課件_第2頁(yè)
嵌入式系統(tǒng)程序設(shè)計(jì)課件_第3頁(yè)
嵌入式系統(tǒng)程序設(shè)計(jì)課件_第4頁(yè)
嵌入式系統(tǒng)程序設(shè)計(jì)課件_第5頁(yè)
已閱讀5頁(yè),還剩277頁(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)程序設(shè)計(jì)大連理工大學(xué)軟件學(xué)院嵌入式系統(tǒng)工程系賴曉晨C/C+語(yǔ)言摘要C語(yǔ)言的歷史和特點(diǎn)預(yù)處理程序位運(yùn)算函數(shù)指針C程序的移植一、C語(yǔ)言的歷史和特點(diǎn)C語(yǔ)言的歷史C語(yǔ)言的特點(diǎn)C語(yǔ)言的優(yōu)良特性結(jié)構(gòu)化語(yǔ)言,代碼數(shù)據(jù)分離包含指針特性,允許對(duì)地址操作語(yǔ)法簡(jiǎn)潔緊湊,但功能強(qiáng)大編程方便,運(yùn)行速度快支持分離編譯C語(yǔ)言的缺點(diǎn)封裝性不如C+,數(shù)據(jù)安全性上有缺陷 類型檢查機(jī)制相對(duì)薄弱 指針的操作帶來(lái)許多不安全因素 比其他高級(jí)語(yǔ)言較難掌握二、預(yù)處理程序C89規(guī)定的預(yù)處理指令有以下幾條#if#ifdef#ifndef#else#elif#endif#define#undef#line#error#pragma#in

2、clude預(yù)處理語(yǔ)句的書(shū)寫(xiě)規(guī)則作用:對(duì)源程序編譯之前做一些處理,生成擴(kuò)展C源程序格式:“#”開(kāi)頭占單獨(dú)書(shū)寫(xiě)行語(yǔ)句尾不加分號(hào)1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)如 #define YES 1 #define NO 0 #define PI 3.1415926 #define OUT printf(“Hello,World”);1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)

3、代替字符序列(宏體)宏體可缺省,表示宏名定義過(guò)如 #define YES 1 #define NO 0 #define PI 3.1415926 #define OUT printf(“Hello,World”);1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)定義位置:任意(一般在函數(shù)外面)作用域:從定義命令到文件結(jié)束#undef可終止宏名作用域 格式: #undef 宏名1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)定義位置:任意(一般在函數(shù)外面)作用域:從定義命令

4、到文件結(jié)束#undef可終止宏名作用域 格式: #undef 宏名例 #define ID 1 main() #undef ID #define ID 0 max() YES原作用域YES新作用域如 if(x=YES) printf(“correct!n”); else if (x=NO) printf(“error!n”);展開(kāi)后: if(x=1) printf(“correct!n”); else if (x=0) printf(“error!n”);1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)宏展開(kāi):預(yù)編譯時(shí),用宏體替換宏

5、名-不作語(yǔ)法檢查定義位置:任意(一般在函數(shù)外面)作用域:從定義命令到文件結(jié)束#undef可終止宏名作用域 格式: #undef 宏名1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)宏展開(kāi):預(yù)編譯時(shí),用宏體替換宏名-不作語(yǔ)法檢查定義位置:任意(一般在函數(shù)外面)作用域:從定義命令到文件結(jié)束#undef可終止宏名作用域 格式: #undef 宏名引號(hào)中的內(nèi)容與宏名相同不置換例 #define ID 1 語(yǔ)句printf( ID );會(huì)輸出ID,而非11. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)

6、代替字符序列(宏體)宏展開(kāi):預(yù)編譯時(shí),用宏體替換宏名-不作語(yǔ)法檢查定義位置:任意(一般在函數(shù)外面)作用域:從定義命令到文件結(jié)束#undef可終止宏名作用域 格式: #undef 宏名宏定義可嵌套,不能遞歸例 #define ID ID + 1 ()引號(hào)中的內(nèi)容與宏名相同不置換例 #define DIS1 10 #define DIS2 DIS1+10 var=DIS2*2;宏展開(kāi):var= 10+10 *2;1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)宏展開(kāi):預(yù)編譯時(shí),用宏體替換宏名-不作語(yǔ)法檢查定義位置:任意(一般在函數(shù)外面)

7、作用域:從定義命令到文件結(jié)束#undef可終止宏名作用域 格式: #undef 宏名宏定義可嵌套,不能遞歸引號(hào)中的內(nèi)容與宏名相同不置換宏定義中使用必要的括號(hào)()例 #define DIS1 10 #define DIS2 (DIS1+10) var=DIS2*2;宏展開(kāi):var= (10+10) *2; 1. 宏定義不帶參數(shù)宏定義一般形式: #define 宏名 宏體功能:用指定標(biāo)識(shí)符(宏名)代替字符序列(宏體)宏展開(kāi):預(yù)編譯時(shí),用宏體替換宏名-不作語(yǔ)法檢查定義位置:任意(一般在函數(shù)外面)作用域:從定義命令到文件結(jié)束#undef可終止宏名作用域 格式: #undef 宏名宏定義可嵌套,不能遞歸

8、引號(hào)中的內(nèi)容與宏名相同不置換宏定義中使用必要的括號(hào)()宏體可以省略,表示宏名已被定義過(guò)/* ch3_1.c*/#include #define Aint main()#ifdef Aprintf(A has been definedn); #elseprintf(A has not been definedn); #endifreturn 0;輸出為:“A has been defined”,即使把宏定義改為:#define A0輸出仍舊為:“A has been defined”。帶參數(shù)宏定義一般形式: #define 宏名(參數(shù)表) 宏體例 #define T (m, n) m*n相當(dāng)于定

9、義了不帶參宏T,其宏體為“(m, n) m*n” 宏展開(kāi):形參用實(shí)參換,其它字符保留例 #define T(m,n) m*n . area=T(3,2);宏展開(kāi): area=3*2;不能加空格帶參數(shù)宏定義一般形式: #define 宏名(參數(shù)表) 宏體宏展開(kāi):形參用實(shí)參換,其它字符保留宏體及各形參外一般應(yīng)加括號(hào)()例 #define T(m,n) m*n . area=T(3,2);宏展開(kāi): area=3*2;例 #define CUBE(x) x*x*x a=4; b=6; z=CUBE(a+b);宏展開(kāi):z=a+b*a+b*a+b;一般寫(xiě)成: #define CUBE(x) (x)*(x)

10、*(x)宏展開(kāi): z=(a+b)*(a+b)*(a+b);#define FUNC(x,y) (x)(y)?(x):(y) .main() int a,b,c,d,t; . t=FUNC(a+b,c+d); 宏展開(kāi):t=(a+b)(c+d)?(a+b):(c+d);int func(int x,int y) return(xy?x:y);main() int a,b,c,d,t; . t=func(a+b,c+d); 例 用宏定義和函數(shù)實(shí)現(xiàn)同樣的功能帶參的宏與函數(shù)區(qū)別帶參宏函數(shù)處理過(guò)程不分配內(nèi)存簡(jiǎn)單的字符置換分配內(nèi)存先求實(shí)參值,再代入形參處理時(shí)間編譯時(shí)程序運(yùn)行時(shí)參數(shù)類型無(wú)類型問(wèn)題定義實(shí)參,形參

11、類型程序長(zhǎng)度變長(zhǎng)不變運(yùn)行速度不占運(yùn)行時(shí)間調(diào)用和返回占時(shí)間Embest開(kāi)發(fā)環(huán)境中的宏定義44b.h有44B0X中各個(gè)特殊功能寄存器的宏定義#define rBWSCON(*(volatile unsigned *)0 x1c80000)#define rBANKCON0(*(volatile unsigned *)0 x1c80004)#define rBANKCON1(*(volatile unsigned *)0 x1c80008)#define rBANKCON2(*(volatile unsigned *)0 x1c8000c)#define rBANKCON3(*(volatile u

12、nsigned *)0 x1c80010)#define rBANKCON4(*(volatile unsigned *)0 x1c80014)#define rBANKCON5(*(volatile unsigned *)0 x1c80018)預(yù)定義宏C89規(guī)范了五個(gè)固有的預(yù)定義宏,分別為:_LINE_:行號(hào)_FILE_:文件名_DATE_:日期_TIME_:時(shí)間_STDC_:1標(biāo)準(zhǔn)C編譯器 0非標(biāo)準(zhǔn)C編譯器預(yù)定義宏#include int main()printf(The current file is: %sn, _FILE_);printf(The current line numbe

13、r is: %dn, _LINE_);printf(today is: %sn, _DATE_);printf(the time is: %sn, _TIME_);if(_STDC_ = 1)printf(this is a standard compilern);else if(_STDC_ = 0)printf(this is not a standard compilern);/exp/pre/macro.c功能:對(duì)源程序中的一部分內(nèi)容只有滿足某種條件的情況下才進(jìn)行編譯。2. 條件編譯#ifdef 標(biāo)識(shí)符程序段1#else程序段2#endif形式1:當(dāng)標(biāo)識(shí)符已經(jīng)被定義過(guò)(使用#defin

14、e),則對(duì)程序段1進(jìn)行編譯,否則編譯程序段2。其中#else部分可以省略。形式1(續(xù)):#define IBM-PC 0 /*或 #define IBM-PC */。#ifdef IBM-PC#define INT 16#else#define INT 32#endif可以用來(lái)提高程序的可移植性形式1(續(xù)):#define DEBUG .#ifdef DEBUGprintf(“x=%d, y=%d”,x,y);#endif可以用來(lái)調(diào)試程序調(diào)試結(jié)束后只需將define行刪掉即可#ifndef 標(biāo)識(shí)符程序段1#else程序段2#endif形式2:當(dāng)標(biāo)識(shí)符未被定義過(guò),則對(duì)程序段1進(jìn)行編譯,否則編譯程

15、序段2。(與形式1正相反)#if 表達(dá)式程序段1#else程序段2#endif形式3:當(dāng)表達(dá)式為真時(shí),則對(duì)程序段1進(jìn)行編譯,否則編譯程序段2。 #include #define CAP 1int main()char string20=I love China;char c; int i=0;c=stringi+;while(c!=0)#if CAPif(c=a&c=z)c-=32;#endifprintf(%c,c);c=stringi+;printf(n);return 0;形式3:(續(xù))3. 文件包含功能:一個(gè)源文件可將另一個(gè)源文件的內(nèi)容全部包含進(jìn)來(lái)一般形式: #include “文件名

16、” 或 #include 直接按標(biāo)準(zhǔn)目錄搜索“” 先在當(dāng)前目錄搜索,再搜索標(biāo)準(zhǔn)目錄可指定路徑3. 文件包含功能:一個(gè)源文件可將另一個(gè)源文件的內(nèi)容全部包含進(jìn)來(lái)一般形式: #include “filename” 或 #include 處理過(guò)程:預(yù)處理時(shí),用被包含文件的內(nèi)容取代該預(yù)處理命令,再把“包含”后的文件作為一個(gè)源文件編譯被包含文件內(nèi)容源文件(*.c)頭文件(*.h)宏定義數(shù)據(jù)結(jié)構(gòu)定義函數(shù)說(shuō)明等實(shí)際上文件名也可以是C源文件,不過(guò)這不是良好的編程風(fēng)格【例3-5】文件包含一下程序包含一個(gè)完整的模塊(function.c、function.h、test.c) /*funtion.h*/#ifndef

17、 _FUNCTION#define _FUNCTIONvoid f();#endif/*function.c*/#include void f()printf(a example of #include.n);/*test.c*/#include #include function.hint main()f();return 0; 頭文件格式4. 其他預(yù)處理指令#error指令強(qiáng)制編譯器停止編譯,主要用于程序調(diào)試。#error指令的一般形式為:編譯到#error時(shí),會(huì)顯示相應(yīng)字符串#error error-message#error舉例#define CON10#define CON21#de

18、fine CON3-1int main()#ifCON1#ifCON2#error run to position1#else#error run to position2#endif#else#ifCON3#error run to position3#else#error run to position4#endif#endif明確程序編譯位置三、位運(yùn)算位運(yùn)算符按位與&取反按位或|左移1. 位與&運(yùn)算規(guī)則:兩個(gè)位都為1,結(jié)果為1,否則為0例如:9&0 x0c結(jié)果為82. 位或|運(yùn)算規(guī)則:兩個(gè)位都為0,結(jié)果為0,否則為1例如:9|0 x0c結(jié)果為0 x0d3. 按位取反運(yùn)算規(guī)則:1變0,0變

19、1用途:使某位取反3. 按位取反 (續(xù))例:使某數(shù)最低位為0int a;a=a&0 xfffffffe3. 按位取反 (續(xù))例:使某數(shù)最低位為0思考:有沒(méi)有隱含的問(wèn)題int a;a=a&0 xfffffffe3. 按位取反 (續(xù))例:使某數(shù)最低位為0/* 16位機(jī) */int a;a=a&0 xffffe/* 32位機(jī) */a=a&0 xfffffffe可移植性變差3. 按位取反 (續(xù))例:使某數(shù)最低位為0a=a&1/* 1能自動(dòng)適應(yīng)16位機(jī)以及32位機(jī) */解決辦法4. 按位異或運(yùn)算規(guī)則:判斷兩位是否相同,同則為0,否則為1用途:使特定位翻轉(zhuǎn) 交換兩個(gè)值,不用臨時(shí)變量4. 按位異或 (續(xù))不

20、通過(guò)中間變量交換兩個(gè)變量的值/*ch3_7.c*/#include int main()int a=21;int b=43;a=ab;b=ba;a=ab;printf(a=%d, b=%dn,a, b);return 0; 5. 左移位運(yùn)算規(guī)則:將一個(gè)數(shù)的全部二進(jìn)制位右移若干位,移出位舍棄,左側(cè)可能補(bǔ)0或者補(bǔ)1,視計(jì)算機(jī)系統(tǒng)不同而不同。符號(hào)問(wèn)題:無(wú)符號(hào)數(shù)右移,左側(cè)補(bǔ)0有符號(hào)數(shù)視計(jì)算機(jī)系統(tǒng)而定:邏輯右移、算術(shù)右移例:循環(huán)右移n位10011111110010101001111111001010N位例:循環(huán)右移n位(續(xù))#include int main()unsigned a,b,c,n;scan

21、f(a=%x,n=%d,&a,&n);b=an;c=c|b;printf(a=%x,c=%xn,a,c);return 0;輸入:a=0 x12345678,n=8顯示:a=12345678,c=78123456四、函數(shù)指針 每一個(gè)函數(shù)模塊都有一個(gè)首地址,稱為函數(shù)的入口地址。 指向函數(shù)的指針?lè)Q為函數(shù)指針,保存的是函數(shù)的入口地址(首地址) 函數(shù)調(diào)用:找到函數(shù)入口地址;傳遞參數(shù) 1. 函數(shù)指針的定義方法格式:int (*ptr1)(int);定義了函數(shù)指針ptr1,此指針只能保存具有一個(gè)整型參數(shù)的整型函數(shù)的首地址。注意 :int *ptr1(int);這是一條函數(shù)聲明語(yǔ)句,表示一個(gè)帶有整數(shù)參數(shù)的函

22、數(shù)返回,返回一個(gè)整型指針。int (*ptr1)(int); 這個(gè)是函數(shù)指針例:以0.1為步長(zhǎng),計(jì)算特定范圍內(nèi)的三角函數(shù)之和。sin(0.1)+sin(0.2)+sin(1.0)cos(0.5)+cos(0.6)+cos(3.0)#include #include double triangle(double(*func)(double), double begin, double end)double step,sum=0.0;for(step=begin;stepend;step+=0.1)sum+=func(step);return sum;int main() double resul

23、t;result=triangle(sin, 0.1, 1.0);printf(the sum of sin from 0.1 to 1.0 is %fn,result);result=triangle(cos, 0.5, 3.0);printf(the sum of cos from 0.5 to 3.0 is %fn,result);return 0;#include #include double triangle(double(*func)(double), double begin, double end)double step,sum=0.0;for(step=begin;step

24、end;step+=0.1)sum+=func(step);return sum;int main() double result;result=triangle(sin, 0.1, 1.0);printf(the sum of sin from 0.1 to 1.0 is %fn,result);result=triangle(cos, 0.5, 3.0);printf(the sum of cos from 0.5 to 3.0 is %fn,result);return 0;2. 用typedef來(lái)簡(jiǎn)化函數(shù)指針對(duì)參數(shù)較多的函數(shù)類型,定義相應(yīng)的函數(shù)指針比較煩瑣,可用typedef關(guān)鍵字簡(jiǎn)化

25、例如typedef double (*FUN)(double a, double b);用typedef來(lái)簡(jiǎn)化函數(shù)指針(續(xù))格式:int (*ptr1)(int);定義函數(shù)指針的別名方法:定義了函數(shù)指針ptr1,此指針只能保存具有一個(gè)整型參數(shù)的整型函數(shù)的首地址。double (*fun1)(double a, double b);typedef double (*FUN)(double a, double b);FUN f1; FUN f2; 用typedef來(lái)簡(jiǎn)化函數(shù)指針(續(xù))格式:int (*ptr1)(int);定義函數(shù)指針的別名方法:(也可以這樣)定義了函數(shù)指針ptr1,此指針只能保存

26、具有一個(gè)整型參數(shù)的整型函數(shù)的首地址。double (*fun1)(double a, double b);typedef double (FUN)(double a, double b);FUN *f1; FUN *f2; 3函數(shù)指針數(shù)組聲明方式定義了表示定義了一個(gè)長(zhǎng)度為4的函數(shù)指針數(shù)組,同時(shí)做了初始化。double ( * fp4 ) (double,double)= f1 , f2 , f3, f4 4函數(shù)指針應(yīng)用在嵌入式操作系統(tǒng)中,經(jīng)常用函數(shù)指針來(lái)完成任務(wù)的調(diào)度。例如uC/OS中,任務(wù)創(chuàng)建的函數(shù)原型為第一個(gè)參數(shù)為函數(shù)指針I(yè)NT8U OSTaskCreate(void(*task)(voi

27、d*pd), void *pdata, OS_STK *ptos, INT8U prio);五、C程序的移植為一種機(jī)器寫(xiě)的程序,經(jīng)常需要在其他硬件、操作系統(tǒng)的平臺(tái)上運(yùn)行,往往需要對(duì)此程序進(jìn)行一些改動(dòng),這個(gè)過(guò)程叫做程序的移植方便移植的程序稱為可移植程序程序不可移植,主要是因?yàn)橛刑嘤布嚓P(guān)的代碼1、避免使用“魔數(shù)”“魔數(shù)”(magic number):依賴于系統(tǒng)或處理器的數(shù)字。例如表示硬盤緩沖區(qū)的大小、屏幕和鍵盤的特定尺寸等數(shù)字?!澳?shù)”的出現(xiàn)使系統(tǒng)可移植性變差。下列代碼本質(zhì)上是不可移植的fread(buf, 256, 1, fp); /緩沖區(qū)為256B使用#define替換“魔數(shù)”程序中要盡量

28、避免“魔數(shù)”的硬編碼,可以用宏來(lái)取代魔數(shù),使可讀性增強(qiáng),而且移植程序時(shí)只要修改宏一處即可#define BUFFER_SIZE 256fread (buf, BUFFER_SIZE, 1, fp); 例一個(gè)圖形處理程序中,需要不同的顏色執(zhí)行不同操作例/*惡劣的例子*/void ShowColor(int color)if ( color = 0 )sub_red();else if ( color = 1 )sub_blue();else if ( color = 2 )sub_green();return ; 例(改進(jìn)后的程序) /*然后在源文件中直接使用這些宏來(lái)判斷*/#include c

29、olor.hvoid ShowColor(int color)if ( color = RED )sub_red();else if ( color = BLUE )sub_blue();else if ( color = GREEN )sub_green();return ; /* color.h*/#define RED 0#define BLUE 1#define GREEN 22、程序分層不同的操作系統(tǒng)為應(yīng)用程序提供了不同的支持,例如windows2000應(yīng)用程序可以有多線程特性,但是windows3.2不可以,應(yīng)用程序?qū)ο到y(tǒng)有依賴型。這種依賴性沒(méi)有具體通用的解決方法,但是可以通過(guò)程序

30、分層來(lái)解決,把系統(tǒng)相關(guān)的代碼放到一起。3、注意數(shù)據(jù)類型的長(zhǎng)度16位機(jī)中整型數(shù)據(jù)是2字節(jié),32位機(jī)為4字節(jié),這會(huì)導(dǎo)致程序的不兼容??梢岳煤陙?lái)重定義數(shù)據(jù)類型#define int16 int/16位機(jī)int16 a;#define int16 short int/32位機(jī)int16 a;注意數(shù)據(jù)類型的長(zhǎng)度(續(xù))16位機(jī)中整型數(shù)據(jù)是2字節(jié),32位機(jī)為4字節(jié),這會(huì)導(dǎo)致程序的不兼容。使用可適應(yīng)任何情況的編碼方式,例如把一個(gè)整型數(shù)據(jù)寫(xiě)入磁盤:fwrite(&i, 4, 1, fp);/不好fwrite(&i, sizeof(int), 1, fp);/好4、對(duì)齊問(wèn)題某些計(jì)算機(jī)允許數(shù)據(jù)邊界地址不對(duì)齊,把這

31、樣的代碼移植到ARM上時(shí)要小心。ARMv5TE前的處理器都不支持地址不對(duì)齊的指針5、大小端問(wèn)題如果兩臺(tái)計(jì)算機(jī)的大小端定義不一致,那么代碼移植時(shí)要做轉(zhuǎn)換6、枚舉類型enum是可移植的,但是不同編譯器中對(duì)enum分配的字節(jié)數(shù)可能不同。不能在不同的編譯器之間對(duì)代碼進(jìn)行交叉連接7、減少內(nèi)嵌匯編C語(yǔ)言的內(nèi)嵌匯編由C編譯器來(lái)負(fù)責(zé)編譯,而不使用armasm或gas。內(nèi)嵌匯編可以提高編程效率,但是會(huì)影響到程序的可移植性。C語(yǔ)言與C+語(yǔ)言的區(qū)別變量定義位置結(jié)構(gòu)體變量數(shù)據(jù)類型輸入輸出動(dòng)態(tài)內(nèi)存分配其他區(qū)別1. 變量定義位置C89要求所有變量都必須定義在塊的最前部C+沒(méi)有這個(gè)要求,可以在程序任意位置定義新的變量2.

32、結(jié)構(gòu)體變量在C+中,struct結(jié)構(gòu)體支持成員函數(shù)的定義,C中不行。如果在C的struct中定義函數(shù),編譯時(shí)會(huì)顯示一個(gè)“field function name declared as function”錯(cuò)誤2. 結(jié)構(gòu)體變量(續(xù))/*ch3_10.c*/struct Aint a;int b();int main()struct A c;c.a=2;return 0;編譯錯(cuò)誤:“ch3_10.c:5: error: field b declared as a function”C+標(biāo)準(zhǔn)可以通過(guò)編譯2. 結(jié)構(gòu)體變量(續(xù))在C語(yǔ)言中,聲明一個(gè)結(jié)構(gòu)體類型A之后,使用下面的語(yǔ)句來(lái)定義結(jié)構(gòu)體變量a:str

33、uct A a;而C+語(yǔ)言中可以省略struct3. 數(shù)據(jù)類型C+中有bool (或boolean類型);C中沒(méi)有這樣的bool類型,均為數(shù)值類型!C編譯器不能通過(guò)編譯,C+編譯器可以bool a;a = 1;4. 輸入輸出 C中使用printf、scanf輸入輸出使用時(shí)不用包含任何頭文件但如果使用g+編譯時(shí)必須加上stdio.h頭文件int a;scanf( %d, &a );printf( 您輸入的數(shù)值是%dn, a );A. scanf()函數(shù)功能:從鍵盤讀入指定格式的數(shù)據(jù)格式:scanf( 控制字符串, 輸入項(xiàng)列表 );注意:scanf中各變量一定是表示地址的標(biāo)識(shí)符(加&)控制字符串控

34、制字符串有兩部分組成:格式說(shuō)明形式:%普通字符空格可打印字符格式說(shuō)明各格式字符及其意義:(詳見(jiàn)C教程)d:輸入一個(gè)十進(jìn)制整數(shù)o:輸入一個(gè)八進(jìn)制整數(shù)x:輸入一個(gè)十六進(jìn)制整數(shù)f:輸入一個(gè)小數(shù)形式的浮點(diǎn)數(shù)e:輸入一個(gè)指數(shù)形式的浮點(diǎn)數(shù)c:輸入一個(gè)字符s:輸入一個(gè)字符串空格在多個(gè)輸入時(shí),一般用空格或回車作為分隔符若以空格作為分隔符,當(dāng)輸入中包含字符類型時(shí),可能產(chǎn)生非預(yù)期的結(jié)果scanf ( %d%c, &a, &ch );輸入:45 q輸出:45 空格空格(續(xù))如下語(yǔ)句會(huì)有正確輸出此處%d后的空格,就可以跳過(guò)字符q前的所有空格scanf ( %d %c, &a, &ch );輸入:45 q輸出:45 q

35、可打印字符看一個(gè)例子輸入為:1,2,q可以得到 a = 1, b = 2, ch = q輸入為:1 2 q除a的值為1外,對(duì)b與ch的賦值失敗scanf ( %d,%d,%c, &a, &b, &ch );B. printf()函數(shù)功能:從缺省輸出設(shè)備(一般為顯示器)輸出規(guī)定格式的字符串格式:printf( 控制字符串, 輸入項(xiàng)列表 );控制字符串控制字符串有兩部分組成:格式說(shuō)明形式:%普通字符空格可打印字符格式說(shuō)明各格式字符及其意義:(詳見(jiàn)C教程)c:按字符型輸出o:按八進(jìn)制輸出d:按十進(jìn)制輸出x:按十六進(jìn)制輸出u:按無(wú)符號(hào)整數(shù)輸出f:按浮點(diǎn)型小數(shù)輸出g:按e和f格式中較短的一種輸出e:按科

36、學(xué)計(jì)數(shù)法輸出普通字符普通字符:可打印字符主要是說(shuō)明字符,按原樣輸出,支持漢字輸出轉(zhuǎn)義字符(例)不能直接打印,控制產(chǎn)生特殊的輸出效果普通字符(續(xù))轉(zhuǎn)義字符示例i = 789,n = 123, a = 92.34567,且i為整型,n為長(zhǎng)整型。 printf( %4dt%7.4fnt%lun, i, a, n );輸出為: 78992.3457 123C語(yǔ)言輸入輸出總結(jié)輸入輸出可能是C和C+的最明顯的區(qū)別C中用scanf(), printf()來(lái)完成輸入輸出操作C+中全局對(duì)象cin、cout來(lái)輸入輸出,比C更方便,而且類型檢查機(jī)制更加完善C+中的使用方式new申請(qǐng)delete釋放C中的使用方式ma

37、lloc()申請(qǐng)free()釋放5. 動(dòng)態(tài)內(nèi)存分配函數(shù)原型:void *malloc( long size );作用:在對(duì)內(nèi)存中分配size各字節(jié),并返回了指向這塊內(nèi)存首地址的指針如果分配失敗,返回NULL返回指針為void*型的,要強(qiáng)制轉(zhuǎn)換A. malloc()函數(shù)函數(shù)原型:void free( void *FirstByte );作用:將之前用malloc申請(qǐng)的空間歸還操作系統(tǒng)否則就導(dǎo)致內(nèi)存泄漏編譯器不會(huì)發(fā)現(xiàn)內(nèi)存泄漏這樣的錯(cuò)誤B. free()函數(shù)C. 函數(shù)的用法/*例 3-11*/#include #include int main()int* p;if(p = (int*)malloc

38、(sizeof(int) = NULL )printf(動(dòng)態(tài)內(nèi)存分配失敗n);exit(1);C. 函數(shù)的用法(續(xù))*p = 100;printf(%dn, *p);free(p);p = NULL;return 0;頭文件:malloc和free被頭文件stdlib.h包含C+中new和delete為關(guān)鍵字,故無(wú)需頭文件包含使用:int *p=(int*)malloc(sizeof(int);int *p = new int;與C+的幾點(diǎn)區(qū)別6. 其他區(qū)別常量表示方法不同C語(yǔ)言不支持引用的概念,而C+支持注釋不同,C89不支持單行注釋(+i)+在C中不合法(a=3)=4在C中不合法不能在fo

39、r循環(huán)頭部定義變量GNU C擴(kuò)展64位整型數(shù)據(jù)類型內(nèi)聯(lián)函數(shù)attribute關(guān)鍵字單行注釋switch case 簡(jiǎn)寫(xiě)預(yù)定義宏結(jié)構(gòu)體和初始化長(zhǎng)度為0的數(shù)組64位整型數(shù)據(jù)類型GNU CC(GNU Compiler Collection)定義了64為整型關(guān)鍵字long long,可以直接操作64位數(shù)據(jù)long long int a = 0 x123;expgnu_clong.c內(nèi)聯(lián)函數(shù)減少函數(shù)調(diào)用開(kāi)銷增加類型檢查,比宏使用更安全inline是建議而非命令attribute關(guān)鍵字關(guān)鍵字attribute通過(guò)向GCC指明有關(guān)代碼的更多信息來(lái)幫助代碼優(yōu)化工作進(jìn)行的更好。attribute關(guān)鍵字(續(xù))下面

40、代碼通過(guò)使用_attribute_,當(dāng)t未被使用時(shí)編譯器不會(huì)警告int main( )float t _attribute_ (unused);return 0;例3-12#include void quit() _attribute_ (noreturn);void quit()exit(1);int test(int n)if ( n 0 )quit();elsereturn 0;int main( )test(1);return 0;函數(shù)不返回【例3-13】/*ch3_13.c*/#include struct s int a2 _attribute_ (aligned (8); ;st

41、ruct tchar a;int b2 _attribute_ (packed); int main()int y _attribute_ (aligned (16);y=1;return 0;以8字節(jié)對(duì)齊單行注釋int main()/long long t1;int t4=3;return 0;expgnu_cnote.cswitch case 簡(jiǎn)寫(xiě)/*ch3_14.c*/#include int main()int t=2;/*傳統(tǒng)方式*/switch(t)case 0 :case 1 :case 2 :printf(012n);break;case 3 :case 4 :case 5 :

42、printf(345n);switch case 簡(jiǎn)寫(xiě)/*GCC擴(kuò)展方式*/switch(t)case 0 . 2 :printf(012n);break;case 3 . 5 :printf(345n);return 0;expgnu_ccase.cgcc允許這樣寫(xiě)。預(yù)定義宏/*ch3_15.c*/#include void f(void)printf(This is function %s n, _FUNCTION_);int main( )printf(This is function %s n, _FUNCTION_);f();return 0;expgnu_cfunc.c結(jié)構(gòu)體初始化

43、struct file_operations ext2_file_operations =llseek:generic_file_llseek,read:generic_file_read,write:generic_file_write,ioctl:ext2_ioctl,mmap:generic_file_mmap,open:generic_file_open,release:ext2_release_file,fsync:ext2_sync_file,;expgnu_cfunc.c結(jié)構(gòu)體初始化 struct file_operations driver_fops =owner: THIS_

44、MODULE,read: driver_read,open: driver_open,release: driver_release,;其他的值被初始化為0.expgnu_cfunc.c長(zhǎng)度為0的數(shù)組GNU還允許結(jié)構(gòu)體的末尾成員是長(zhǎng)度為0的數(shù)組錯(cuò)誤處理機(jī)制C語(yǔ)言錯(cuò)誤處理機(jī)制系統(tǒng)日志文件 一、C語(yǔ)言的錯(cuò)誤處理機(jī)制C標(biāo)準(zhǔn)中有幾個(gè)錯(cuò)誤處理機(jī)制 預(yù)定義宏預(yù)定義全局變量若干庫(kù)函數(shù)1. assert宏assert宏定義在assert.h中語(yǔ)法格式:作用:計(jì)算表達(dá)式expression的值,如果為0,那么首先向stderr打印一條出錯(cuò)信息,然后調(diào)用abort()函數(shù)終止程序運(yùn)行。assert (expres

45、sion)【例3-16】/*ch3_16.c*/#include#include #includeint main()char *p;p = getenv(HOME);assert(p);printf(HOME=%sn,p);p = getenv(NOTEXIST);assert(p);printf(NOTEXIST=%sn,p);return 0;/exp/error/badptr.cassert的缺點(diǎn)assert的調(diào)用會(huì)影響程序的運(yùn)行效率,有時(shí)希望程序中的assert不會(huì)起作用,這可以通過(guò)在程序前部包含assert.h之前定義一個(gè) NDEBUG來(lái)實(shí)現(xiàn)?!纠?-17】/*ch3_17.c*/

46、#define NDEBUG#include#include #includeint main()char *p;p = getenv(HOME);assert(p);printf(HOME=%sn,p);p = getenv(NOTEXIST);assert(p);printf(NOTEXIST=%sn,p);return 0;/exp/error/badptr2.cassert使用注意事項(xiàng)當(dāng)使用#define NDEBUG來(lái)禁用assert宏時(shí),注意assert宏中隱含的某些操作不能完成,而這些代碼可能對(duì)后面的操作有關(guān)鍵作用。定義NDEBUG,p賦值行未執(zhí)行,使用p時(shí)出錯(cuò)。assert使用

47、注意事項(xiàng)舉例#define NDEBUGassert(p=malloc(sizeof(char)*100);free(p);#define NDEBUGp=malloc(sizeof(char)*100);assert(p);free(p);應(yīng)該按照這種方式來(lái)編寫(xiě)P是野指針assert使用討論assert宏只提供了一種粗糙的終止程序運(yùn)行的方式,這種方法并不理想。理想的方式是“適當(dāng)?shù)慕导?jí)”,在不同層次的出錯(cuò)處理都失敗了,別無(wú)選擇的情況下才終止程序的運(yùn)行。在不得不警告或者提示用戶之前能成功的處理的出錯(cuò)越多,程序就越健壯。2. 位置指示宏C標(biāo)準(zhǔn)定義了兩個(gè)宏:_LINE_FILE_把這兩個(gè)宏用于可以更

48、精確的定位程序的出錯(cuò)位置?!纠?-18】#include #include int show_environment(char* e, int num, char *name)char* p=getenv(e);if(p!=NULL)printf(the environment is: %sn, p);return 0;elseprintf(error occured at %d of %s.n, num,name);return 1; /exp/error/filefcn.c【例3-18】(續(xù))int main()char* e1=HOME;char* e2=NOTEXIST;int res

49、;res = show_environment(e1, _LINE_, _FILE_);if (res)return 1;res = show_environment(e2, _LINE_, _FILE_);if (res)return 1;return 0;/exp/error/filefcn.c3. 標(biāo)準(zhǔn)庫(kù)函數(shù)本節(jié)的“標(biāo)準(zhǔn)庫(kù)”是指任何支持ANSI/ISO C標(biāo)準(zhǔn)的C環(huán)境的一部分變量、宏、函數(shù)。本節(jié)介紹5個(gè)函數(shù)和一個(gè)變量。stdlib.h:void abort(void);void exit(int status);int atexit(void (*fcn)(void);stdio.hvo

50、id perror(const char *s);string.hchar *strerror(int errnum);errno.hint errno;3. 標(biāo)準(zhǔn)庫(kù)函數(shù)(續(xù))C語(yǔ)言還提供了一些標(biāo)準(zhǔn)庫(kù)函數(shù)和全局變量用來(lái)支持錯(cuò)誤處理,具體包含5個(gè)函數(shù),以及一個(gè)全局變量,任何ANSI/ISO C標(biāo)準(zhǔn)的實(shí)現(xiàn)都包含這些特性A. errnoLinux系統(tǒng)調(diào)用和許多庫(kù)函數(shù)在出錯(cuò)時(shí)都要把全局變量errno設(shè)置為一個(gè)非0值,唯一對(duì)應(yīng)一種出錯(cuò)的情況。在希望通過(guò)訪問(wèn)errno以確定錯(cuò)誤類型前,要人為的把errno設(shè)置為0,因?yàn)闆](méi)有任何一個(gè)函數(shù)可以把errno設(shè)置為0。errno定義在頭文件stdlib.h中【例3

51、-19】/*ch3_19.c*/#include #include #include #include int main(void)FILE *fp;errno=0;fp=fopen(notexist,r);if(errno)printf(Open file failed.n);elseprintf(Open file successfully.n);/exp/error/errno.c檢測(cè)errno值【例3-19】(續(xù))printf(try again. n);errno=0;fp=fopen(notexist,w);if(errno)printf(Open file failed.n);e

52、lseprintf(Open file successfully.n);return 0;檢測(cè)errno值/exp/error/errno.c清0變量errno的常見(jiàn)值宏值含義EPERM1操作不被允許ENOENT2文件或目錄不存在ESRCH3進(jìn)程不存在EINTR4系統(tǒng)調(diào)用中斷EIO5I/O錯(cuò)誤ENXIO6設(shè)備或地址不存在E2BIG7參數(shù)太長(zhǎng)EBADF9錯(cuò)誤的文件號(hào)ECHILD10子進(jìn)程不存在變量errno的常見(jiàn)值(續(xù))宏值含義EAGAIN11重試ENOMEM12沒(méi)有內(nèi)存EACCES13沒(méi)有權(quán)限EFAULT14地址錯(cuò)誤EBUSY 16設(shè)備或資源忙EEXIST17文件存在ENODEV19設(shè)備不存在

53、ENOTDIR20不是目錄EISDIR21是目錄變量errno的常見(jiàn)值(續(xù))宏值含義EINVAL22無(wú)效參數(shù)EMFILE24打開(kāi)的文件太多ENOTTY25不是打印機(jī)EFBIG27文件太長(zhǎng)ENOSPC28磁盤上沒(méi)有空間EPIPE32管道中斷EDOM33數(shù)學(xué)參數(shù)超出函數(shù)定義域ERANGE34數(shù)學(xué)結(jié)果不可表示EILSEQ84非法字節(jié)序列變量errno的常見(jiàn)值(續(xù))宏值含義ERESTART85中斷的系統(tǒng)調(diào)用應(yīng)該重啟EUSERS87用戶數(shù)太多ANSI/ISO CPOSIXB. abort函數(shù)abort函數(shù)的功能是立刻終止程序運(yùn)行,并且不會(huì)執(zhí)行由atexit()登記過(guò)的函數(shù)原型:void abort(vo

54、id);【例3-20】/*ch3_20.c*/#include #include int main(void)printf(Hello everybody.n);abort();printf(you can not get here. n);return 0;/exp/error/boom.cC. exit()函數(shù)exit()函數(shù)于abort()的區(qū)別在于終止程序前會(huì)執(zhí)行由atexit()登記的函數(shù)函數(shù)原型:#includevoid exit(int status);exit的類型是void,即沒(méi)有返回值。status是exit函數(shù)返回給操作系統(tǒng)的退出碼,可以是任何數(shù)值,而在stdlib.h中

55、定義了兩個(gè)宏:EXIT_SUCCESS和EXIT_FAILURED. atexit函數(shù)atexit函數(shù)登記在程序正常結(jié)束時(shí)要調(diào)用的函數(shù),或者由exit調(diào)用或者由main函數(shù)返回來(lái)調(diào)用。函數(shù)原型:#includeint atexit(void (*function)(void);傳遞給atexit的函數(shù)不帶任何參數(shù),也沒(méi)有返回值。如果function登記成功,則atexit返回0,否則返回1。如果執(zhí)行abort函數(shù),則不會(huì)調(diào)用atexit登記的函數(shù)。【例3-21】/*ch3_21.c*/#include #include void test()printf(you can still get h

56、ere. n);int main(void)printf(hello everybody. n);if(atexit(test)!=0)printf(atexit() run failed.n);exit(EXIT_FAILURE);printf(goodbye everybody. n);return 0;E. strerror函數(shù)strerror函數(shù)返回一個(gè)指向字符串的指針,該字符串描述了和errnum相對(duì)應(yīng)的錯(cuò)誤信息,如把errnum傳遞給strerror,則可得到此信息。函數(shù)原型:#includechar* strerror(int errnum);F. perror函數(shù)perror函

57、數(shù)輸出系統(tǒng)錯(cuò)誤信息。函數(shù)原型:#include #include void perror(const char *s);如果系統(tǒng)調(diào)用失敗,一般會(huì)設(shè)置errno。perror()函數(shù)首先打印字符串參數(shù)s,然后添加一個(gè)冒號(hào)和一個(gè)空格,然后是對(duì)應(yīng)于errno的錯(cuò)誤信息和一個(gè)換行符。F. perror函數(shù)(續(xù))以下兩行等價(jià):perror( “something error”);printf(“something error: %s”,strerror(errno);perror與strerror的比較前者短小精干,完全能應(yīng)付一般使用。后者可以對(duì)錯(cuò)誤信息再編輯,可以應(yīng)用于需要精心設(shè)計(jì)的場(chǎng)合【例3-22】

58、/*ch3_22.c*/#include #include #include #include #include int main(void)FILE *fp;char* p;errno=0;fp=fopen(notexist,r);if(errno)perror(Open file);/exp/error/errinfo.c【例3-22】(續(xù))errno=0;fp=fopen(notexist,r);if(errno)p=strerror(errno);fprintf(stderr, Open file: %sn, p);return 0;/exp/error/errinfo.c二、系統(tǒng)日志

59、文件Linux的兩個(gè)系統(tǒng)守護(hù)進(jìn)程klogd和syslogd提供了集中的系統(tǒng)日志功能。klogd供內(nèi)核和運(yùn)行在內(nèi)核空間的程序,特別是設(shè)備驅(qū)動(dòng)程序使用。syslogd控制著來(lái)自用戶空間的消息的產(chǎn)生。日志消息的優(yōu)先級(jí)寫(xiě)入系統(tǒng)日志的消息由它的級(jí)別(level)和功能(facility)來(lái)控制。級(jí)別指出了消息的重要程度和嚴(yán)重性功能告訴syslogd守護(hù)進(jìn)程是哪個(gè)程序發(fā)出的消息。一條日志消息優(yōu)先級(jí)由級(jí)別和功能共同組成syslog的日志級(jí)別:level級(jí)別嚴(yán)重性LOG_EMERG系統(tǒng)不可用LOG_ALERT要求立刻處理LOG_CRIT重大錯(cuò)誤,比如硬盤故障LOG_ERR錯(cuò)誤條件LOG_WARNING警告錯(cuò)誤

60、LOG_NOTICE正常但重要的消息LOG_INFO純粹的通報(bào)消息LOG_DEBUG調(diào)試跟蹤輸出syslog的功能值:facility功能消息源LOG_AUTHPRIV私有的安全和授權(quán)消息LOG_CRON時(shí)鐘守護(hù)進(jìn)程(crond和atd)LOG_DAEMON其他系統(tǒng)守護(hù)進(jìn)程LOG_KERN內(nèi)核消息LOG_LOCAL0-7為本地/站點(diǎn)使用而保留LOG_LPR打印機(jī)子系統(tǒng)LOG_MAIL郵件子系統(tǒng)LOG_NEWS新聞組子系統(tǒng)LOG_SYSLOGsyslogd產(chǎn)生的內(nèi)部消息LOG_USER一般用戶級(jí)消息(默認(rèn))LOG_UUCPuucp子系統(tǒng)發(fā)送消息的原則選取與消息內(nèi)容相適應(yīng)的級(jí)別值。對(duì)于用戶級(jí)程序,

溫馨提示

  • 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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 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)論