




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、C 語言基本數(shù)據(jù)類型簡介1 .概述C語言包含的數(shù)據(jù)類型如下圖所示:2.各種數(shù)據(jù)類型介紹整型整形包括短整型、整形和長整形。短整形shorta=1;整形一般占4個(gè)字節(jié)(32位),最高位代表符號(hào),0表示正數(shù),1表示負(fù)數(shù),取值范圍是-4847,在內(nèi)存中的存儲(chǔ)順序是地位在前、高位在后,例如0 x在內(nèi)存中的存儲(chǔ)如下:地址:0 x0012ff780 x0012ff790 x0012ff7a0 x0012ff7b數(shù)據(jù):78563412定義:用int關(guān)鍵字,舉例如下:inta=6;長整形longa=10;浮點(diǎn)型浮點(diǎn)型包括單精度型和雙精度型。單精度型floata=;雙精度型一般占8個(gè)字節(jié)(64位)doublea=
2、;地址:0 x0012ff780 x0012ff790 x0012ff7a0 x0012ff7b0 x0012ff7c0 x0012ff7d0 x0012ff7e0 x0012ff7f數(shù)據(jù):0000000000001240字符類型在各種不同系統(tǒng)中,字符類型都占一個(gè)字節(jié)(8位)。定義如下:charc=a;也可以用字符對(duì)應(yīng)的ASCII碼賦值,如下:charc=97;3.數(shù)據(jù)類型與“模子”short、int、long、char、float、double這六個(gè)關(guān)鍵字代表C語言里的六種基本數(shù)據(jù)類型。浮點(diǎn)型,又稱實(shí)型,也稱單精度。一般占4個(gè)字節(jié)(32位),地址:0 x0012ff780 x0012ff79
3、0 x0012ff7a0 x0012ff7b數(shù)據(jù):00009040怎么去理解它們呢舉個(gè)例子:見過藕煤千的那個(gè)東西吧(沒見過煤球總見過吧)。那個(gè)東西叫藕煤器,拿著它在和好的煤堆里這么一咔,一個(gè)煤球出來了。半徑12cm,12個(gè)孔。不同型號(hào)的藕煤器咔出來的煤球大小不一樣,孔數(shù)也不一樣。這個(gè)藕煤器其實(shí)就是個(gè)模子?,F(xiàn)在我們聯(lián)想一下,short、int、long、char、float、double這六個(gè)東東是不是很像不同類型的藕煤器啊拿著它們在內(nèi)存上咔咔咔,不同大小的內(nèi)存就分配好了,當(dāng)然別忘了給它們?nèi)€(gè)好聽的名字。在32位的系統(tǒng)上short短整型的內(nèi)存2byte;int整型的內(nèi)存4byte;long長整型
4、的內(nèi)存4byte;float單精度浮點(diǎn)型的內(nèi)存4byte;僅能接收7位有效數(shù)字double雙精度浮點(diǎn)型的內(nèi)存8byte;可以接收16位有效數(shù)字char字符型的內(nèi)存1byte。fabs單精度浮點(diǎn)型內(nèi)存4byte.(注意這里指一般情況,可能不同的平臺(tái)還會(huì)有所不同,具體平臺(tái)可以用sizeof關(guān)鍵字測試一下)很簡單吧咔咔咔很爽吧是很簡單,也確實(shí)很爽,但問題就是你咔出來這么多內(nèi)存塊,你總不能給他取名字叫做x1,x2,x3,x4,x5或者長江1號(hào),長江2號(hào)一吧。它們長得這么像(不是你家的老大,老二,老三),過一陣子你就會(huì)忘了到底哪個(gè)名字和哪個(gè)內(nèi)存塊匹配了(到底誰嫁給誰了啊A/)。所以呢,給他們?nèi)∫粋€(gè)好的名
5、字絕對(duì)重要。下面我們就來研究研究取什么樣的名字好。4.變量的命名規(guī)則1)命名應(yīng)當(dāng)直觀且可以拼讀,可望文知意,便于記憶和閱讀。標(biāo)識(shí)符最好采用英文單詞或其組合,不允許使用拼音。程序中的英文單詞一般不要太復(fù)雜,用詞應(yīng)當(dāng)準(zhǔn)確。2)命名的長度應(yīng)當(dāng)符合min-length&max-information”原則。C是一種簡潔的語言,命名也應(yīng)該是簡潔的。例如變量名MaxVal就比MaxValueUntilOverflow好用。標(biāo)識(shí)符的長度一般不要過長,較長的單詞可通過去掉元音形成縮寫。另外,英文詞盡量不縮寫,特別是非常用專業(yè)名詞,如果有縮寫,在同一系統(tǒng)中對(duì)同一單詞必須使用相同的表示法,并且注明其意思。
6、3)當(dāng)標(biāo)識(shí)符由多個(gè)詞組成時(shí),每個(gè)詞的第一個(gè)字母大寫,其余全部小寫。比如:intCurrentVal;這樣的名字看起來比較清晰,遠(yuǎn)比一長串字符好得多。4)盡量避免名字中出現(xiàn)數(shù)字編號(hào),如Value1,Value2等,除非邏輯上的確需要編號(hào)。比如驅(qū)動(dòng)開發(fā)時(shí)為管腳命名,非編號(hào)名字反而不好。初學(xué)者總是喜歡用帶編號(hào)的變量名或函數(shù)名,這樣子看上去很簡單方便,但其實(shí)是一顆顆定時(shí)炸彈。這個(gè)習(xí)慣初學(xué)者一定要改過來。5)對(duì)在多個(gè)文件之間共同使用的全局變量或函數(shù)要加范圍限定符為范圍限定符)(GUI_,etc)標(biāo)識(shí)符的命名規(guī)則:6)標(biāo)識(shí)符名分為兩部分:規(guī)范標(biāo)識(shí)符前綴(后綴)+含義標(biāo)識(shí)。非全局變量可以不用使用范圍限定符前
7、綴。7)作用域前綴命名規(guī)則(建議使用模塊名(縮寫)作No.標(biāo)炳類型作用域前綴1GlobalVariableFileStaticoblnative)nFuuciionStaticVariablef4Auroraiiablea5GlobalFunctiongRLX6StaticFunctionn8)數(shù)據(jù)類型前綴命名規(guī)則No.PrefixSuffixDataTypeExampleRemark1btbitBitVariable;bbooleanbooleanbVariable;3ccharcharcVaiiable:411iininiiVaiiable;5sshoitintshortfmrsellab
8、le:61longfinilongintiVaiiable:7uunsiaiediiit uusiguedmtuiVariable:8ddoubledouble岫riaMe:9ffloatfloat(Variable:10Ppointervoidrp如訕le:指針前綴11VvoidvoidvVanable;13sternuiieoumAstWiable;14ststructsmiaAstAaiiable:15stunionmiioiiAstVanable:16小fimctionpointvoid(*Q)GetModeFimcList_aXvoid)17an學(xué)ofchai八疝abljaTABLE
9、J1AX:18_stJSttypedefemoStiuci/uQ1011iypedefstructSMEventOpt(unsignedcl皿unsignedintctar:SMEventOptst.SMEvemOprjst:當(dāng) 日 定義 結(jié) 構(gòu)懶 類 型時(shí) 使 用 期 后絳當(dāng) 自 定義 結(jié) 構(gòu)數(shù) 據(jù) 類型 為 指針 類 型時(shí) 使 用邛 鼾 后雙;9)含義標(biāo)識(shí)命名規(guī)則,變量命名使用名詞性詞組,函數(shù)命名使用動(dòng)詞性詞組。例如:No變敬目祠動(dòng)劃的過去分詞)悔眥地含義1DaiaGotFrouiSDDataGotFromSD從SD中取融就TDataDeleiedfromSDDaraDeletedFrom
10、SD從卬中M除的轆變量含義標(biāo)識(shí)符構(gòu)成:目標(biāo)詞+動(dòng)詞(的過去分詞)+狀語+目的地;N0變量名變量名動(dòng)詞 (一般現(xiàn)時(shí)) 目標(biāo)詞狀語陰勺地含義1GetDataFromSDGetDaraFromSD從SD中取得數(shù)據(jù)一DeleteDalalramSDDeleteDataFromSD從SD中刷除數(shù)據(jù)函數(shù)含義標(biāo)識(shí)符構(gòu)成:動(dòng)詞(一般現(xiàn)時(shí))+目標(biāo)詞+狀語+目的地;10)程序中不得出現(xiàn)僅靠大小寫區(qū)分的相似的標(biāo)識(shí)符。例如:intx,X;變量x與X容易混淆voidfoo(intx);函數(shù)foo與FOO容易混淆voidFOO(floatx);這里還有一個(gè)要特別注意的就是1(數(shù)字1)和l(小寫字母l)之間,0(數(shù)字0)和
11、o(小寫字母o)之間的區(qū)別。這兩對(duì)真是很難區(qū)分的,我曾經(jīng)的一個(gè)同事就被這個(gè)問題折騰了一次。11)一個(gè)函數(shù)名禁止被用于其它之處。例如:#includevoidfoo(intp_1)intx=p_1;voidstatic_p(void)intfoo=1u;12)所有宏定義、枚舉常數(shù)、只讀變量全用大寫字母命名,用下劃線分割單詞。例如:constintMAX_LENGTH=100;以小數(shù)形式輸出單,雙精度實(shí)數(shù)我的指點(diǎn)對(duì)你受益)變量的聲明有兩種情況:1、一種是需要建立存儲(chǔ)空間的。例如:inta在聲明的時(shí)候就已經(jīng)建立了存儲(chǔ)空間。2、另一種是不需要建立存儲(chǔ)空間的。例如:externinta其中變量a是在別的
12、文件中定義的。前者是定義性聲明(definingdeclaration)或者稱為定義(definition)”,而后者是引用性聲明(referncingdeclaration)”,從廣義的角度來講聲明中包含著定義,即定義是聲明的一個(gè)特例,所以并非所有的聲明都是定義,例如:inta它既是聲明,同時(shí)又是定義。然而對(duì)于externa來講它只是聲明不是定義。一般的情況下我們常常這樣敘述,把建立空間的聲明稱之為“定義”,而把不需要建立存儲(chǔ)空間的聲明稱之為“聲明”。很明顯我們在這里指的聲明是范圍比較窄的,即狹義上的聲明,也就是說非定義性質(zhì)的聲明,例如:在主函數(shù)中:intmain()externintA;w
13、hile)函數(shù)類型所占的字節(jié)short短整型的內(nèi)存2byte;int整型的內(nèi)存4byte;long長整型的內(nèi)存4byte;float單精度浮點(diǎn)型的內(nèi)存4byte;僅能接收7位有效數(shù)字double雙精度浮點(diǎn)型的內(nèi)存8byte;可以接收16位有效數(shù)字char字符型的內(nèi)存1byte。fabs單精度浮點(diǎn)型內(nèi)存4byte.(C中的CONST編輯const是一個(gè)C語言(ANSIC)的關(guān)鍵字,它限定一個(gè)變量不允許被改變,產(chǎn)生靜態(tài)作用。使用const在一定程度上可以提高程序的安全性和可靠性。另外,在觀看別人代碼的時(shí)候, 清晰理解const所起的作用, 對(duì)理解對(duì)方的程序也有一些幫助。 另外CONS在其他編程語言
14、中也有出現(xiàn), 如C+、PHP5B#、HC08CC#(1)可以定義const常量,具有不可變性。例如:constintMax=100;Max+會(huì)產(chǎn)生錯(cuò)誤;(2)便于進(jìn)行類型檢查,使編譯器對(duì)處理內(nèi)容有更多了解,消除了一些隱患。例如:voidf(constinti)編譯器就會(huì)知道i是一個(gè)常量,不允許修改;(3)可以避免意義模糊的數(shù)字出現(xiàn),同樣可以很方便地進(jìn)行參數(shù)的調(diào)整和修改。同宏定義一樣,可以做到不變則已,一變都變!如(1)中,如果想修改Max的內(nèi)容,只需要:constintMax=youwant;即可!(4)可以保護(hù)被修飾的東西,防止意外的修改,增強(qiáng)程序的健壯性。還是上面的例子,如果在函數(shù)體內(nèi)修改
15、了i,編譯器就會(huì)報(bào)錯(cuò);例如:voidf(constinti)i=10;.doublei=Pi;=-break;case#:.break;while,do-while和for的區(qū)別未知循環(huán)次數(shù)時(shí):While(條件)先判斷,滿足條件后循環(huán)。do-while(條件)先循環(huán)一次,在判斷,滿足條件再循環(huán)已知循環(huán)次數(shù)時(shí):for(初始值;條件;#+)先判斷,滿足條件后break和continuebreak跳由整個(gè)循環(huán),循環(huán)結(jié)束。continue跳由本次循環(huán),循環(huán)繼續(xù)。變量(全局變量和局部變量)全局變量:不在函數(shù)中定義的變量局部變量:在函數(shù)中定義的變量。汪息:在一個(gè)函數(shù)中定義過的變量(如:sum),在下一函數(shù)
16、還可以用它定義,之間不沖突。說明函數(shù)中的變量的值只在本函數(shù)中使用,不在其它函數(shù)中使用。所以全局變量也可以被定義為局部變量(因?yàn)?,他們之間的值并不沖突)。例如:#includeVoidSwap(inta,intb);Intmain();宏與全局變量的區(qū)別1作用時(shí)間不同。宏定義在編譯期間即會(huì)使用并替換,而全局變量要到運(yùn)行時(shí)才可以。2本質(zhì)類型不同。宏定義的只是一段字符,在編譯的時(shí)候被替換到引用的位置。在運(yùn)行中是沒有宏定義的概念的。而變量在運(yùn)行時(shí)要為其分配內(nèi)存。3宏定義不可以被賦值,即其值一旦定義不可修改,而變量在運(yùn)行過程中可以被修改。4宏定義只有在定義所在文件,或引用所在文件的其它文件中使用。而全局
17、變量可以在工程所有文件中使用,只要再使用前加一個(gè)聲明就可以了。換句話說,宏定義不支持extern。#define宏名宏體#definePI#defineSET_PROC(proc)inttemp;temp=get_temp();=(proc);set_temp(temp);宏函數(shù)假設(shè)有這樣一個(gè)需求:一個(gè)項(xiàng)目需要 250250 個(gè)函數(shù),但這些函數(shù)體內(nèi)容完全相同,僅函數(shù)名不同,例如 FuncFunc。、FunciFunci、Func2.Func2.等等,這樣的要求怎么實(shí)現(xiàn)呢(先不要問有沒有如此變態(tài)的需求)當(dāng)然可以使用手工先寫 Func0Func0 函數(shù)體, 再寫 FunciFunci 函數(shù)體, .
18、, 一直寫到函數(shù)體 Func250Func250。假設(shè)寫完了后,項(xiàng)目需求有變,函數(shù)體內(nèi)有變化,還要從頭開始一個(gè)一個(gè)改.!宏代換函數(shù)函數(shù)式宏定義:#defineMAX(a,b)(a)(b)(a):(b)普通函數(shù):MAX(a,b)returnaba:b;盡管函數(shù)式宏定義和普通函數(shù)相比有很多缺點(diǎn),但只要小心使用還是會(huì)顯著提高代碼的執(zhí)行效率,畢竟省去了分配和釋放棧幀、傳參、傳返回值等一系列工作,因此那些簡短并且被頻繁調(diào)用的函數(shù)經(jīng)常用函數(shù)式宏定義來代替實(shí)現(xiàn)。格式:#define+名+(形參)功能:代換由一個(gè)字符型內(nèi)存變量的內(nèi)容。若與后面的字符無空格分界,則&函數(shù)后的“.”必須有。例如,m=4*3
19、A2+5”這樣的使用需求會(huì)碰到的: 一個(gè)項(xiàng)目創(chuàng)建了 N N 個(gè)線程, 每個(gè)線程訪問相同的一個(gè)回調(diào)函數(shù),并傳遞進(jìn)入相同的參數(shù),但是這個(gè)回調(diào)函數(shù)不能只寫一個(gè),應(yīng)該是一個(gè)線程對(duì)應(yīng)一個(gè)回調(diào)函數(shù),就是這樣一個(gè)問題。C語言宏定義使用技巧寫好C語言, 漂亮的宏定義很重要, 使用宏定義可以防止出錯(cuò), 提高可移植性,可讀性, 方便性等等。下面列舉一些成熟軟件中常用得宏定義。1,防止一個(gè)頭文件被重復(fù)包含#ifndefCOMDEF_H#defineCOMDEF_H*/typedefunsignedlongintuint32;/*Unsigned32bitvalue*/typedefunsignedshortuint
20、16;/*Unsigned16bitvalue*/typedefunsignedcharuint8;/*Unsigned8bitvalue*/typedefsignedlongintint32;/*Signed32bitvalue*/typedefsignedshortint16;/*Signed16bitvalue*/typedefsignedcharint8;/*Signed8bitvalue*/*/typedefunsignedshortword;bitvaluetype.*/typedefunsignedlongdword;bitvaluetype.*/typedefunsignedc
21、haruint1;8bitvaluetype.*/typedefunsignedshortuint2;bitvaluetype.*/typedefunsignedlonguint4;bitvaluetype.*/typedefsignedcharint1;8bitvaluetype.*/typedefsignedshortint2;bitvaluetype.*/typedeflongintint4;Signed32bitvaluetype.*/typedefsignedlongsint31;bitvalue*/typedefsignedshortsint15;bitvalue*/typedef
22、signedcharsint7;8bitvalue*/3,得到指定地址上的一個(gè)字節(jié)或字#defineMEM_B(x)(*(byte*)(x)#defineMEM_W(x)(*(word*)(x)4,求最大值和最小值/*Unsinged16/*Unsigned32/*Unsigned/*Unsigned16/*Unsigned32/*Signed/*Signed16/*/*Signed32/*Signed16/*Signed#defineMAX(x,y)(x)(y)(x):(y)#defineMIN(x,y)(x)field)/*lint+e545*/6,得到一個(gè)結(jié)構(gòu)體中field所占用的字節(jié)數(shù)
23、#defineFSIZ(type,field)sizeof(type*)0)-field)7,按照LSB格式把兩個(gè)字節(jié)轉(zhuǎn)化為一個(gè)Word#defineFLIPW(ray)(word)(ray)0)*256)+(ray)1)8,按照LSB格式把一個(gè)Word轉(zhuǎn)化為兩個(gè)字節(jié)#define(ray)1=(val)&0 xFF)9,得到一個(gè)變量的地址(word寬度)#defineB_PTR(var)(byte*)(void*)&(var)#defineW_PTR(var)(word*)(void*)&(var)10,得到一個(gè)字的高位和低位字節(jié)#defineWORD_LO(*)(b
24、yte)(word)(*)&255)#defineWORD_HI(*)(byte)(word)(*)8)11,返回一個(gè)比X大的最接近的8的倍數(shù)#defineRND8(x)(x)+7)/8)*8)12,將一個(gè)字母轉(zhuǎn)換為大寫#defineUPCASEC)(c)=a&(c)=0&(c)=A&(c)=a&(c)(val)(val)+1:(val)16,返回?cái)?shù)組元素的個(gè)數(shù)#defineARR_SIZE(a)(sizeof(a)/sizeof(a0)17,返回一個(gè)無符號(hào)數(shù)n尾的值MOD_BY_POWER_OF_TWO(X,n尸X%(2An)(dword)(val)&
25、amp;(dword)(mod_by)-1)18,對(duì)于IO空間映射在存儲(chǔ)空間的結(jié)構(gòu), 輸入輸出處理(/(volatilebyte*)(port)(/(volatileword*)(port)(/(volatiledword*)(port)(*(volatilebyte*)(port)=(byte)(*(volatileword*)(port)=(word)(val)#defineoutpdw(port,val)(*(volatiledword*)(port)=(dword)(val)2005-9-9添加19,使用一些宏跟蹤調(diào)試ANSI標(biāo)準(zhǔn)說明了五個(gè)預(yù)定義的宏名。它們是:_DATE_TIME_S
26、TDC_如果編譯不是標(biāo)準(zhǔn)的,則可能僅支持以上宏名中的幾個(gè),或根本不支持。記住編譯程序#define#defineinp(port)#defineinpw(port)#defineinpdw(port)#defineoutp(port,val)(val)#defineoutpw(port,val)也許還提供其它預(yù)定義的宏名。_LINE_及_FILE_宏指令在有關(guān)#line的部分中已討論,這里討論其余的宏名。_DATE_宏指令含有形式為月/日/年的申,表示源文件被翻譯到代碼時(shí)的日期。源代碼翻譯到目標(biāo)代碼的時(shí)間作為用包含在_TIME_中。用形式為時(shí):分:秒。如果實(shí)現(xiàn)是標(biāo)準(zhǔn)的,則宏_STDC_含有十進(jìn)
27、制常量1。如果它含有任何其它數(shù),則實(shí)現(xiàn)是非標(biāo)準(zhǔn)的??梢远x宏,例如:當(dāng)定義了_DEBUG輸出數(shù)據(jù)信息和所在文件所在行#ifdef_DEBUG#defineDEBUGMSG(msg,date)printf(msg);printf(d%d%d,date,_LINE_,_FILE_)#else#defineDEBUGMSG(msg,date)#endif20,宏定義防止使用是錯(cuò)誤用小括號(hào)包含。例如:#defineADD(a,b)(a+b)用dowhile(0)語句包含多語句防止錯(cuò)誤例如:a+;應(yīng)用時(shí):if(.)DO(a,b);.符號(hào)的使用宏的解釋方法我們能碰到的宏的使用宏使用中的陷阱常見的基礎(chǔ)性問題
28、關(guān)于#和#在C語言的宏中,#的功能是將其后面的宏參數(shù)進(jìn)行字符串化操作(Stringfication),簡單說就是在對(duì)它所引用的宏變量通過替換后在其左右各加上一個(gè)雙引號(hào)。比如下面代碼中的宏:#defineWARN_IF(EXP)doif(EXP)fprintf(stderr,Warning:#EXPn);while(0)那么實(shí)際使用中會(huì)出現(xiàn)下面所示的替換過程:WARN_IF(divider=0);被替換為doif(divider=0)fprintf(stderr,Warningdivider=0n);while。;這樣每次divider(除數(shù))為0的時(shí)候便會(huì)在標(biāo)準(zhǔn)錯(cuò)誤流上輸出一個(gè)提示信息。而#t
29、t稱為連接符(concatenator),用來將兩個(gè)Token連接為一個(gè)Token。注意這里連接的對(duì)象是Token就行,而不一定是宏的變量。比如你要做一個(gè)菜單項(xiàng)命令名和函數(shù)指針組成的結(jié)構(gòu)體的數(shù)組,并且希望在函數(shù)名和菜單項(xiàng)命令名之間有直觀的、名字上的關(guān)系。那么下面的代碼就非常實(shí)用:structcommandchar*name;voidfunction)(void);;#defineCOMMAND(NAME)NAME,NAME#_command.COMMANDS這里充當(dāng)一個(gè)代碼生成器的作用,這樣可以在一定程度上減少代碼密度, 間接地也可以減少不留心所造成的錯(cuò)誤。我們還可以n個(gè)#符號(hào)連接n+1個(gè)To
30、ken,這個(gè)特性也是#符號(hào)所不具備的。比如:#defineLINK_MULTIPLE(a,b,c,d)a#_#b#_#c#_#dtypedefstruct_record_typeLINK_MULTIPLE(name,company,position,salary);.的使用.在C宏中稱為VariadicMacro,也就是變參宏。比如:#definemyprintf(templt,.)fprintf(stderr,templt,VAARGS_).)fprintf(stderr,templt,args)第一個(gè)宏中由于沒有對(duì)變參起名,我們用默認(rèn)的宏_VA_ARGS_替代它。第二個(gè)宏中,我們顯式地命名
31、變參為args,那么我們在宏定義中就可以用args來代指變參了。同C語言的stdcall一樣,變參必須作為參數(shù)表的最有一項(xiàng)出現(xiàn)。當(dāng)上面的宏中我們只能提供第一個(gè)參數(shù)templt時(shí),C標(biāo)準(zhǔn)要求我們必須寫成:myprintf(templt,);的形式。這時(shí)的替換過程為:myprintf(Error!n,);替換為:fprintf(stderr,Error!n,);這是一個(gè)語法錯(cuò)誤,不能正常編譯。這個(gè)問題一般有兩個(gè)解決方法。首先,GNUCP提供的解決方法允許上面的宏調(diào)用寫成:myprintf(templt);而它將會(huì)被通過替換變成:fprintf(stderr,Error!n,);很明顯,這里仍然會(huì)產(chǎn)
32、生編譯錯(cuò)誤(非本例的某些情況下不會(huì)產(chǎn)生編譯錯(cuò)誤)。除了這種方式外,c99和GNUCP部支持下面的宏定義方式:#definemyprintf(templt,.)fprintf(stderr,templt,#VARARGS_)這時(shí),#&個(gè)連接符號(hào)充當(dāng)?shù)淖饔镁褪钱?dāng)_VAR_ARGS的時(shí)候,消除前面的那個(gè)逗號(hào)。那么此時(shí)的翻譯過程如下:myprintf(templt);被轉(zhuǎn)化為:fprintf(stderr,templt);這樣如果templt合法,將不會(huì)產(chǎn)生編譯錯(cuò)誤。宏是如何解釋的宏在日常編程中的常見使用宏使用中的陷阱這里列出了一些宏使用中容易出錯(cuò)的地方,以及合適的使用方式。錯(cuò)誤的嵌套Misn
33、esting宏的定義不一定要有完整的、配對(duì)的括號(hào),但是為了避免出錯(cuò)并且提高可讀性,最好避免這樣使用。由操作符優(yōu)先級(jí)引起的問題一OperatorPrecedenceProblem由于宏只是簡單的替換,宏的參數(shù)如果是復(fù)合結(jié)構(gòu),那么通過替換之后可能由于各個(gè)參數(shù)之間的操作符優(yōu)先級(jí)高于單個(gè)參數(shù)內(nèi)部各部分之間相互作用的操作符優(yōu)先級(jí),如果我們不用括號(hào)保護(hù)各個(gè)宏參數(shù),可能會(huì)產(chǎn)生預(yù)想不到的情形。比如:#defineceil_div(x,y)(x+y-1)/y那么a=ceil_div(b&c,sizeof(int);將被轉(zhuǎn)化為:a=(b&c+sizeof(int)-1)/sizeof(int);.
34、if(condition。)MY_MACRO(a);else.這樣會(huì)由于多出的那個(gè)分號(hào)產(chǎn)生編譯錯(cuò)誤。為了避免這種情況出現(xiàn)同時(shí)保持MY_MACRO(X)勺這種寫法,我們需要把宏定義為這種形式:#defineMY_MACRO(x)do/*line1*/*line2*/*line3*/while。這樣只要保證總是使用分號(hào),就不會(huì)有任何問題。DuplicationofSideEffects這里的SideEffect是指宏在展開的時(shí)候?qū)ζ鋮?shù)可能進(jìn)行多次Evaluation(也就是取值),但是如果這個(gè)宏參數(shù)是一個(gè)函數(shù),那么就有可能被調(diào)用多次從而達(dá)到不一致的結(jié)果,甚至?xí)l(fā)生更嚴(yán)重的錯(cuò)誤。比如:#defin
35、emin(X,Y)(X)(Y)(Y):(X)c=min(a,foo(b);這時(shí)foo()函數(shù)就被調(diào)用了兩次。為了解決這個(gè)潛在的問題,我們應(yīng)當(dāng)這樣寫min(X,Y)這個(gè)宏:#definemin(X,Y)(typeof(X)x_=(X);typeof(Y)y_=(Y);(x_16)#defineLow16bit(REG)(REG16)對(duì)于這種寫法完成的功能在大多數(shù)情況是足夠了,這里不討論。主要談?wù)撨@種寫法的負(fù)面影響,如果在程序中分別在不同的語句中使用High16bit和Low16bit,那么就可能那就是Sideeffect,特別寄存器REG狀態(tài)寄存器,他的狀態(tài)可能隨時(shí)變化,那么引起的問題就是高低1
36、6b根本取的不是同一個(gè)時(shí)刻狀態(tài)寄存器。這種錯(cuò)誤在程序中找出就比較難了。在這里我把條件弱化了,試想在一個(gè)宏體中,如果對(duì)參數(shù)多次取值也是可能引起問題,那就更難了。分類:c+對(duì)帶參數(shù)的宏,在調(diào)用中,不僅要宏展開,而且要用實(shí)參去代換形參。C語言允許宏帶有參數(shù)。在宏定義中的參數(shù)稱為形式參數(shù),在宏調(diào)用中的參數(shù)稱為實(shí)際參數(shù)。帶參宏定義的一般形式為:#define宏名(形參列表)字符串在字符串中含有各個(gè)形參。帶參宏調(diào)用的一般形式為:宏名(實(shí)參列表);例如:#defineM(y)y*y+3*y/宏定義/Codek=M(5);宏調(diào)用在宏調(diào)用時(shí),用實(shí)參5去代替形參y,經(jīng)預(yù)處理宏展開后的語句為 k=5*5+3*5?!?/p>
37、示例】輸出兩個(gè)數(shù)中較大的數(shù)。1.#include2.#defineMAXa,b)(ab)a:main()4.intx,y,max;5.printf(inputtwonumbers:);6.scanf(%d%d”,&x,&y);7.max=MAXx,y);8.printf(max=%dn,max);9.return0;10.運(yùn)行結(jié)果:inputtwonumbers:1020max=20程序第2行進(jìn)行了帶參宏定義,用宏名 MAX 表示條件表達(dá)式(ab)a:b,形參a、b均出現(xiàn)在條件表達(dá)式中。程序第7行 max=MAX(x,y)為宏調(diào)用,實(shí)參x、y,將代換形參bo宏展開后
38、該語句為:max=(xy)x:y;用于計(jì)算x、y中的大數(shù)。對(duì)帶參宏定義的說明1)帶參宏定義中,形參之間可以出現(xiàn)空格,但是宏名和形參列表之間不能有空格出現(xiàn)。例如把:#defineMAX(a,b)(ab)a:b寫為:#defineMAX(a,b)(ab)a:b將被認(rèn)為是無參宏定義,宏名MAX代表字符串(a,b)(ab)a:b。宏展開時(shí),宏調(diào)用語句max=MAX(x,y);將變?yōu)椋簃ax=(a,b)(ab)a:b(x,y);這顯然是錯(cuò)誤的。2)在帶參宏定義中,形式參數(shù)不分配內(nèi)存單元,因此不必作類型說明。而宏調(diào)用中的實(shí)參有具體的值,要用它們?nèi)ゴ鷵Q形參,因此必須作類型說明。這是與函數(shù)中的情況不同的。在函數(shù)中,形參和實(shí)參是兩個(gè)不同的量,各有自己的作用域,調(diào)用時(shí)要把實(shí)參值賦予形參,進(jìn)行“值傳遞”。而在帶參宏中,只是符號(hào)代換,不存在值傳遞的問題。3)在宏定
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 自動(dòng)駕駛技術(shù)測試合作協(xié)議
- 《創(chuàng)新課程設(shè)計(jì):物理游戲化教學(xué)法教案》
- 八年級(jí)英語語法知識(shí)總結(jié)與提升教學(xué)教案
- 鋼筋綁扎承包合同
- 阿甘正傳節(jié)選與人生哲學(xué)的思考:英語文學(xué)賞析教學(xué)教案
- 網(wǎng)絡(luò)安全風(fēng)險(xiǎn)評(píng)估及防御合作協(xié)議
- 裝修工程區(qū)域消防安全協(xié)議書
- 航空航天材料科技知識(shí)重點(diǎn)梳理
- 數(shù)據(jù)空間發(fā)展戰(zhàn)略藍(lán)皮書內(nèi)容
- 知識(shí)產(chǎn)權(quán)授權(quán)轉(zhuǎn)讓與使用協(xié)議
- 財(cái)務(wù)審計(jì)服務(wù)方案投標(biāo)文件(技術(shù)方案)
- 專題二網(wǎng)絡(luò)消費(fèi)者購買行為分析(課件)職教高考電子商務(wù)專業(yè)《網(wǎng)絡(luò)營銷實(shí)務(wù)》
- 中建有限空間作業(yè)施工方案
- 2024年四川省宜賓市“兩?!笔痉秴^(qū)招聘雇員制聘用人員12人歷年高頻500題難、易錯(cuò)點(diǎn)模擬試題附帶答案詳解
- 2024脈沖式布袋除塵器設(shè)備運(yùn)行情況記錄表(模板)
- 管理批次管理辦法
- 機(jī)器人維護(hù)協(xié)議范文
- 助理值班員(中級(jí))技能鑒定理論題庫(濃縮400題)
- 診所負(fù)責(zé)人變更申請(qǐng)書
- DL-T5334-2016電力工程勘測安全規(guī)程
- (高清版)JTG D50-2017 公路瀝青路面設(shè)計(jì)規(guī)范
評(píng)論
0/150
提交評(píng)論