国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

學(xué)習(xí)筆記---預(yù)處理

2019-11-11 04:03:00
字體:
供稿:網(wǎng)友

預(yù)處理(編譯預(yù)處理)

預(yù)處理命令:C語言中以符號(hào)“#”開頭的命令

示例:#define...   #include...   #ifdef...

含義:

1.在對(duì)程序進(jìn)行編譯之前,根據(jù)預(yù)處理命令對(duì)程序進(jìn)行相應(yīng)處理。

2.經(jīng)過預(yù)處理后編譯器才可以對(duì)程序進(jìn)行編譯等處理,得到可供執(zhí)行的目標(biāo)代碼。

示意圖:

解析:

如圖,源程序經(jīng)過編譯和連接生成可執(zhí)行文件。而預(yù)處理命令將在編譯之前被執(zhí)行。

宏定義

釋義:可以用#define命令將一個(gè)指定的標(biāo)識(shí)符(即宏名)來代表一個(gè)字符串

分類:

不帶參數(shù):

語法:#define  標(biāo)識(shí)符  字符串

應(yīng)用法則:原樣替換

典型應(yīng)用:符號(hào)常量

代碼示例:

#include <stdio.h>#include <stdlib.h>/*這個(gè)程序用來測試預(yù)處理中的不帶參數(shù)的宏定義*/#define PI 3.1415926int main(){    float r,l,s;    PRintf("please enter r:");    scanf("%f",&r);    l=2*PI*r;    s=r*r*PI;    printf(" l: %f /n s: %f /n",l,s);    return 0;}結(jié)果:

解析:

定義PI3.1415926之后,在編譯前將把代碼段中所有PI都替換成3.1415926,之后再生成目標(biāo)文件。這種方式能降低出錯(cuò)的概念,也能提高程序的可讀性。

注意:絕對(duì)不要用 #define PI 3.1415926;這樣的形式!因?yàn)楹甓x的法則是原樣替換,所以會(huì)把分號(hào)也原樣代入程序!在上述的示例程序中l的計(jì)算方程就會(huì)變成l=2*3.1415926;*r;一個(gè)語句中出現(xiàn)兩個(gè)分號(hào),就會(huì)帶來致命的差錯(cuò)!

帶參數(shù):

語法:#define 宏名(參數(shù)表)  字符串

例:

#define S(a,b) a*b...area=S(2,4);解析:

此處area=S(2,4)將在編譯前被解析為:area=2*4

代碼示例:

#include <stdio.h>#include <stdlib.h>/*這個(gè)程序用來測試預(yù)處理中的帶參數(shù)的宏定義*/#define S(a,b) a*bint main(){    printf("矩形1面積;%d/n",S(2,4));    printf("矩形2面積:%.2f/n",S(2.3,4.5));    return 0;}結(jié)果:

解析:

如上,程序成功計(jì)算出了結(jié)果。使用帶參數(shù)的宏定義同樣能降低出錯(cuò)的概念。同時(shí)大大提升代碼的可讀性。

深度理解:

帶參數(shù)宏定義和函數(shù)的區(qū)別:

1.函數(shù)在編譯后會(huì)生成目標(biāo)代碼,且在程序運(yùn)行到調(diào)用行,會(huì)跳轉(zhuǎn)入函數(shù)中繼續(xù)執(zhí)行。而帶參數(shù)的宏定義將在編譯前被替換成一個(gè)常量表達(dá)式。在目標(biāo)代碼中也不會(huì)出現(xiàn)任何痕跡。

2.函數(shù)的參數(shù)、返回值類型都是有嚴(yán)格定義的。而宏定義只是進(jìn)行機(jī)械的替換,參數(shù)以及其計(jì)算的結(jié)果的數(shù)據(jù)類型都需要自行把握。

帶參數(shù)宏定義的易錯(cuò)點(diǎn):

代碼示例:

#include <stdio.h>#include <stdlib.h>/*這個(gè)程序用來測試預(yù)處理中的帶參數(shù)的宏定義的性質(zhì)*/#define PI 3.1415926#define S1(r) PI*r*r#define S2(r) PI*(r)*(r)int main(){    float a,b;    a=1;    b=2;    printf("test1:/nr=%.2f,area=%.2f/n",a+b,S1(a+b));    printf("test2:/nr=%.2f,area=%.2f/n",a+b,S2(a+b));    return 0;}結(jié)果:

解析:

1.如上,S1S2看似差別不大。但得到的結(jié)果卻完全不同。

2.宏定義的法則為原樣替換,所以對(duì)于S1(1+2)將被替換為:PI*1+2*1+2。可以看到,因?yàn)橛?jì)算符號(hào)優(yōu)先級(jí)的原因,算式完全扭曲了我們希望得到的結(jié)果。

3.S2所做的是,給每個(gè)參數(shù)都帶上一個(gè)小括號(hào),這就解決了S1所遇到的問題,并能夠計(jì)算出正確的結(jié)果。事實(shí)上,這也是代碼規(guī)范化的一部分。認(rèn)識(shí)的這一點(diǎn)之后,在使用宏定義時(shí),應(yīng)當(dāng)盡量給每個(gè)參數(shù)都加上小括號(hào)。以減少錯(cuò)誤的發(fā)生。

文件包含

釋義:一個(gè)源文件可以將另外一個(gè)源文件的全部內(nèi)容包含進(jìn)來。

語法: #include  "文件地址"  或  #include  <文件地址>

圖示:

如圖,在file1.c中加入#include "file2.c"效果相當(dāng)于將file2.c中所有的代碼拷貝至當(dāng)前位置。

應(yīng)用:將源文件與頭文件分離,提高代碼重用性。具體例子在:http://blog.csdn.net/aketoshknight/article/details/54837779大型程序基礎(chǔ)---調(diào)用外部頭文件部分

特點(diǎn)——節(jié)省程序設(shè)計(jì)人員的重復(fù)勞動(dòng):

1.將常用的一組固定常量的定義組成一個(gè)文件——方便,易修改。

2.庫函數(shù)的開發(fā)者將對(duì)被調(diào)用的函數(shù)的原型聲明寫入頭文件,程序員只需要#include<頭文件> ——大大簡化了程序。

3.一行#include ,相當(dāng)于寫幾十、幾百,甚至更多行內(nèi)容,提高了效率。

起源——模塊化程序設(shè)計(jì)的產(chǎn)物:

1.便于多個(gè)程序員分別編程。

2.將公用的符號(hào)常量或宏定義等可單獨(dú)組成一個(gè)文件,在其他文件的開頭用包含命令包含該文件即可使用。

3.公用的聲明只寫一次,除節(jié)省時(shí)間,更可觀的是減少出錯(cuò)。

include 命令的兩種形式:

1.#include <文件名>

例:#include <stdio.h>

特點(diǎn):編譯器將在系統(tǒng)目錄(不同的操作系統(tǒng)可能有不同的系統(tǒng)目錄,也可以在編譯器的設(shè)置中自行修改系統(tǒng)目錄的地址)中尋找要包含的文件,如果無法找到該文件,則給出出錯(cuò)信息。

注:對(duì)于系統(tǒng)提供的頭文件,既可用尖括號(hào)形式,也可用雙撇號(hào)形式,但一般用尖括號(hào)形式的效率更高。

2.#include "文件名"

例:#include "mymodule.h"

特點(diǎn):編譯器先按雙引號(hào)中指出的文件路徑和文件名查找(如果給出了E:test.c這樣形式的路徑,便會(huì)去該處尋找。如果如上所示只給出文件名,將默認(rèn)在用戶當(dāng)前目錄(程序所在的目錄)中尋找),若找不到,再去系統(tǒng)目錄中查找。若仍舊無法找到,則給出出錯(cuò)信息。

注:若要包含的是用戶自己編寫的文件,一般保存在程序目錄中,因此宜用雙撇號(hào)形式。

GCC編譯器中的頭文件和庫函數(shù):

頭文件:

如上,MinGW便是一種GCC編譯器,其中的include文件夾里存放著大量系統(tǒng)頭文件可供引用。

庫函數(shù):

如上,在MinGWlib文件夾中,存放著大量的.o目標(biāo)文件,以及多種.o目標(biāo)文件打包而成的.a文件(在代碼連編的連接階段,便是使用這里的文件和程序源文件的目標(biāo)代碼進(jìn)行連接的)。

注:以上圖示是GCC編譯器的體系,而在VC++VS中,目標(biāo)文件將打包成.lib.dll文件,而非.a文件。

條件編譯

釋義:根據(jù)需要,只編譯程序中的某一部分。

常用形式1:

//define 標(biāo)識(shí)符#ifdef 標(biāo)識(shí)符    程序段1#else    程序段2#endif解析:

ifdef可看成if define的簡寫。當(dāng)所指定的標(biāo)識(shí)符已經(jīng)被#define命令定義過,則在程序編譯階段只編譯程序段1,否則編譯程序段2。#endif用來限定#ifdef命令的范圍,其中#else部分可以省略。

常用形式2:

//define 標(biāo)識(shí)符#ifndef 標(biāo)識(shí)符    程序段1#else    程序段2#endif解析:

ifndef可看成if not define的簡寫。和第一種正好相反。

常用形式3:

#if 常量表達(dá)式    程序段1#else    程序段2#endif解析:

和常用的if else條件選擇結(jié)構(gòu)的區(qū)別在于增加了代表預(yù)處理的#。如果常量表達(dá)式的值為真(非0),則對(duì)程序段1進(jìn)行編譯,否則對(duì)程序段2進(jìn)行編譯。因此可以使程序在不同條件下完成不同的功能。

代碼示例1:

#include <stdio.h>#include <stdlib.h>/*這個(gè)程序用來測試預(yù)處理中的條件編譯*///宏定義常量DEBUG#define DEBUGint main(){    int x=1,y=2;    //ifdef 既if define如果宏定義了XX    #ifdef DEBUG        printf("x=%d,y=%d/n",x,y);//當(dāng)宏定義DEBUG存在,這句代碼將被編譯。而如果宏定義DEBUG不存在,這句代碼將不被編譯。    #endif // DEBUG    printf("x*y=%d/n",x*y);    return 0;}結(jié)果1:

代碼示例2:

#include <stdio.h>#include <stdlib.h>/*這個(gè)程序用來測試預(yù)處理中的條件編譯*///宏定義常量DEBUG//#define DEBUGint main(){    int x=1,y=2;    //ifdef 既if define如果宏定義了XX    #ifdef DEBUG        printf("x=%d,y=%d/n",x,y);//當(dāng)宏定義DEBUG存在,這句代碼將被編譯。而如果宏定義DEBUG不存在,這句代碼將不被編譯。    #endif // DEBUG    printf("x*y=%d/n",x*y);    return 0;}結(jié)果2:

解析:

1.如上示例,通過改變宏定義,運(yùn)用#ifdef 即可控制代碼中的某一部分是否被編譯。

2.雖然使用if  else條件判斷也能實(shí)現(xiàn)類似的效果,但此處的條件判斷是預(yù)處理的一種。既這些代碼將在源文件編譯前就被執(zhí)行,并且在編譯后的.o目標(biāo)文件中將不會(huì)出現(xiàn)這些代碼。

3.這種方式適合在調(diào)試程序時(shí)使用,當(dāng)調(diào)試完畢時(shí),只需要取消對(duì)DEBUG的宏定義,即可一次性消除大量調(diào)試用代碼對(duì)程序的影響。

代碼示例3:

#include <stdio.h>#include <stdlib.h>/*這個(gè)程序用來測試預(yù)處理中的條件編譯*/#define R 1int main(){    float c,r,s;    printf("input a number:/n");    scanf("%f",&c);    #if R        r=3.14159*c*c;        printf("area of round is:%f/n",r);    #else        s=c*c;        printf("area of square is:%f/n",s);    #endif // R    return 0;}結(jié)果:

解析:

套用if else的使用經(jīng)驗(yàn),可以十分容易的理解。

深入理解:

文件包含的弊端:

假設(shè)個(gè)文件A.h  B.c  C.c

A.h:

int test=10;....B.c:

include "A.h"int main(){    ....}C.c:

include "A.h"include "B.c"int main(){    ....}當(dāng)編寫較大的程序時(shí),常會(huì)出現(xiàn)此種交叉包含的情況。這樣,在C.c中就會(huì)出現(xiàn)A.h被多次包含的問題。既,A.h中的test變量被多次定義。導(dǎo)致編譯出錯(cuò)。

解決方案:

A.h:

#ifndef MYHEADER#define MYHEADER 1    #define PI 3.14    int NUM=3    .....#endif解析:

1.如上,使用條件編譯之后,完美的解決了這個(gè)問題。2.這是一種編碼規(guī)范的標(biāo)準(zhǔn),為了減少代碼的BUG,應(yīng)當(dāng)用這種方式定義自己的頭文件。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 霍林郭勒市| 理塘县| 怀柔区| 滁州市| 乡宁县| 东乌珠穆沁旗| 南郑县| 崇礼县| 武宣县| 公主岭市| 泊头市| 贵溪市| 青川县| 南投县| 珲春市| 庆云县| 洞头县| 扎兰屯市| 林西县| 道孚县| 武邑县| 靖安县| 略阳县| 道真| 平和县| 堆龙德庆县| 西藏| 扬州市| 元阳县| 潢川县| 黔西| 仙居县| 新营市| 辽源市| 沙河市| 上高县| 夏河县| 聂荣县| 交口县| 和林格尔县| 大足县|