最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言預(yù)處理詳解

 更新時(shí)間:2021年10月11日 15:52:22   作者:/少司命  
這篇文章主要給大家介紹了關(guān)于C語言之預(yù)處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一,預(yù)定義符號(hào)

__FILE__      //進(jìn)行編譯的源文件
__LINE__     //文件當(dāng)前的行號(hào)
__DATE__    //文件被編譯的日期
__TIME__    //文件被編譯的時(shí)間
__STDC__    //如果編譯器遵循ANSI C,其值為1,否則未定義
 int main()
{
	printf("%s\n", __FILE__);
	printf("%d\n", __LINE__);
	printf("%s\n", __DATE__);
	printf("%s\n", __TIME__);
	//printf("%d\n", __STDC__);//因?yàn)閂S不支持ANSI C,其實(shí)__STDC__未定義
	//gcc 是支持的
	//gcc對(duì)C語言語法的支持非常好
 	return 0;
}

這些預(yù)定義符號(hào)都是語言內(nèi)置的,例題如下

 int main()
 {
	 printf("file:%s line:%d\n", __FILE__, __LINE__);
	 return 0;
 }

二,#define

1,#define 定義標(biāo)識(shí)符

#define name stuff
#define MAX 100
#define reg register    //為 register這個(gè)關(guān)鍵字,創(chuàng)建一個(gè)簡(jiǎn)短的名字
#define STR "HEHE"
int main()
{
	int a = 3;
	int b = 20;
	if (a == 4)
		b = MAX;
	else
		b = -a;
	register int num = 100;
	reg int num2 = 200;
 	int m = MAX;
	printf("%d\n", MAX);
	printf("%d\n", m);
	printf("%s\n", STR);
 	return 0;
}

在define定義標(biāo)識(shí)符的時(shí)候,要不要在最后加上 ; ?

#define MAX 1000;
int main()
{
	int x = 1;
	int max;
	if (x==1)
	{
		max = MAX;//這里替換為 MAX 1000;;語法錯(cuò)誤
	}
	else
	{
		max = 0;
	}
	printf("%d", max);
	return 0;
}

2,#define 定義宏

#define 機(jī)制包括了一個(gè)規(guī)定,允許把參數(shù)替換到文本中,這種實(shí)現(xiàn)通常稱為宏(macro)或定義宏(define macro)。

下面是宏的申明方式:

#define name( parament-list ) stuff 其中的 parament-list 是一個(gè)由逗號(hào)隔開的符號(hào)表,它們可能出現(xiàn)在 stuff中。

注意: 參數(shù)列表的左括號(hào)必須與name緊鄰。 如果兩者之間有任何空白存在,參數(shù)列表就會(huì)被解釋為stuff的一部 分。

#define SQUARE( x ) x * x

這個(gè)宏接收一個(gè)參數(shù) x=5.

SQUARE( 5 );

程序會(huì)如何表達(dá),如下

5 * 5
int a = 5;
printf("%d\n" ,SQUARE( a + 1) );

觀察上面的代碼,你會(huì)認(rèn)為結(jié)果是多少?

替換文本時(shí),參數(shù)x被替換成a + 1,所以這條語句實(shí)際上變成了: printf ("%d\n",a + 1 * a + 1 );

在宏定義上加上兩個(gè)括號(hào),這個(gè)問題便輕松的解決了:

#define SQUARE(x) (x) * (x)

這樣預(yù)處理之后就產(chǎn)生了預(yù)期的效果:

printf ("%d\n",(a + 1) * (a + 1) );
#define SQUARE(X) ((X)*(X))
 int main()
{
	int a = 5;
	int ret = SQUARE(a+5);
	//int ret = a + 5 * a + 5;
	//int ret = ((a) * (a));
	printf("%d\n", ret);
 	return 0;
}

這里還有一個(gè)宏定義:

#define DOUBLE(x) (x) + (x)

定義中我們使用了括號(hào),想避免之前的問題,但是這個(gè)宏可能會(huì)出現(xiàn)新的錯(cuò)誤。

int a = 5; 
printf("%d\n" ,10 * DOUBLE(a)); 

好像打印100,但事實(shí)上打印的是55. 我們發(fā)現(xiàn)替換之后:

printf ("%d\n",10 * (5) + (5));

這個(gè)問題,的解決辦法是在宏定義表達(dá)式兩邊加上一對(duì)括號(hào)就可以了。

#define DOUBLE(x) ( ( x ) + ( x ) )
#define DOUBLE(X) ((X)+(X))
 int main()
{
	int ret = 10 * DOUBLE(2);
	//int ret = 10 * 2 + 2;
 	printf("%d\n", ret);
 	return 0;
}

提示:所以用于對(duì)數(shù)值表達(dá)式進(jìn)行求值的宏定義都應(yīng)該用這種方式加上括號(hào),避免在使用宏時(shí)由于參數(shù)中的操作符或 鄰近操作符之間不可預(yù)料的相互作用。

3,#define 替換規(guī)則

在調(diào)用宏時(shí),首先對(duì)參數(shù)進(jìn)行檢查,看看是否包含任何由#define定義的符號(hào)。如果是,它們首先被替換。

替換文本隨后被插入到程序中原來文本的位置。對(duì)于宏,參數(shù)名被他們的值替換。

最后,再次對(duì)結(jié)果文件進(jìn)行掃描,看看它是否包含任何由#define定義的符號(hào)。如果是,就重復(fù)上述處理過程。

注意:

宏參數(shù)和#define 定義中可以出現(xiàn)其他#define定義的變量。但是對(duì)于宏,不能出現(xiàn)遞歸。

當(dāng)預(yù)處理器搜索#define定義的符號(hào)的時(shí)候,字符串常量的內(nèi)容并不被搜索。

#define PRINT(n) printf("the value of "#n" is %d\n", n)
 int main()
{
	int a = 10;
	PRINT(a);
	int b = 20;
	PRINT(b);
	return 0;
}

用#define連接字符串

#define PRINT(FORMAT, VALUE)
printf("the value is "FORMAT"\n", VALUE);
PRINT("%d", 10);
#define PRINT(n) printf("the value of "#n" is %d\n", n)
 int main()
{
	int a = 10;
	printf("the value of a is %d\n", a);
	int b = 20;
	printf("the value of b is %d\n", b);
	printf("hello world\n");
	printf("hello ""world\n");
	return 0;
}

三,##的作用

1,概念

##可以把位于它兩邊的符號(hào)合成一個(gè)符號(hào)。 它允許宏定義從分離的文本片段創(chuàng)建標(biāo)識(shí)符。

#define ADD_TO_SUM(num, value) 
sum##num += value; 
 ADD_TO_SUM(5, 10);//作用是:給sum5增加10.
#define CAT(X,Y) X##Y
 int main()
{
	int class103 = 100;
	printf("%d\n", CAT(class, 103));
	printf("%d\n", CAT(1, 2));
	return 0;
}

2,帶副作用的宏參數(shù)

當(dāng)宏參數(shù)在宏的定義中出現(xiàn)超過一次的時(shí)候,如果參數(shù)帶有副作用,那么你在使用這個(gè)宏的時(shí)候就可能出現(xiàn)危險(xiǎn),導(dǎo) 致不可預(yù)測(cè)的后果。副作用就是表達(dá)式求值的時(shí)候出現(xiàn)的永久性效果。 例如:

x+1;//不帶副作用
x++;//帶有副作用

MAX宏可以證明具有副作用的參數(shù)所引起的問題。

int main()
{
	int a = 10;
	int b = a + 1;//b得到的是11,a不變
	int b = ++a;//b得到的是11,但是a變了,這個(gè)表達(dá)式是有副作用的
	return 0;
}
int Max(int x, int y)
{
	return x > y ? x : y;
}
 int main()
{
	int a = 5;
	int b = 8;
 	//int m = MAX(a++, b++);
	//int m = ((a++) > (b++) ? (a++) : (b++));
	//函數(shù)的參數(shù)是計(jì)算后再傳進(jìn)去的
	int m = Max(a++, b++);
 	printf("m=%d\n", m);//8
	printf("a=%d\n", a);//6
	printf("b=%d\n", b);//9
  	return 0;
}

//宏的實(shí)現(xiàn) - 1
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
int Max(int x, int y)
{
	return x > y ? x : y;
}
 int main()
{
	int a = 5;
	int b = 8;
	//宏的參數(shù)是不計(jì)算直接替換進(jìn)去的
	//替換進(jìn)去進(jìn)去后參與運(yùn)算
 	int m = Max(a++, b++);
 	printf("m=%d\n", m);//8
	printf("a=%d\n", a);//6
	printf("b=%d\n", b);//9
 	return 0;

3,宏和函數(shù)對(duì)比

宏通常被應(yīng)用于執(zhí)行簡(jiǎn)單的運(yùn)算。比如在兩個(gè)數(shù)中找出較大的一個(gè)。

#define MAX(a, b) ((a)>(b)?(a):(b)) 

用于調(diào)用函數(shù)和從函數(shù)返回的代碼可能比實(shí)際執(zhí)行這個(gè)小型計(jì)算工作所需要的時(shí)間更多。所以宏比函數(shù)在程序的規(guī)模和速度方面更勝一籌。

更為重要的是函數(shù)的參數(shù)必須聲明為特定的類型。所以函數(shù)只能在類型合適的表達(dá)式上使用。反之這個(gè)宏怎可 以適用于整形、長(zhǎng)整型、浮點(diǎn)型等可以用于>來比較的類型。宏是類型無關(guān)的。

宏的劣勢(shì)

每次使用宏的時(shí)候,一份宏定義的代碼將插入到程序中。除非宏比較短,否則可能大幅度增加程序的長(zhǎng)度。

宏是沒法調(diào)試的。

宏由于類型無關(guān),也就不夠嚴(yán)謹(jǐn)。

宏可能會(huì)帶來運(yùn)算符優(yōu)先級(jí)的問題,導(dǎo)致程容易出現(xiàn)錯(cuò)。

屬 性 #define定義宏 函數(shù)
代 碼 長(zhǎng) 度 每次使用時(shí),宏代碼都會(huì)被插入到程序中。除了非常小的宏 之外,程序的長(zhǎng)度會(huì)大幅度增長(zhǎng) 函數(shù)代碼只出現(xiàn)于一個(gè)地方;每次使 用這個(gè)函數(shù)時(shí),都調(diào)用那個(gè)地方的同 一份代碼
執(zhí) 行 速 度 更快 存在函數(shù)的調(diào)用和返回的額外開銷, 所以相對(duì)慢一些
操 作 符 優(yōu) 先 級(jí) 宏參數(shù)的求值是在所有周圍表達(dá)式的上下文環(huán)境里,除非加 上括號(hào),否則鄰近操作符的優(yōu)先級(jí)可能會(huì)產(chǎn)生不可預(yù)料的后 果,所以建議宏在書寫的時(shí)候多些括號(hào) 函數(shù)參數(shù)只在函數(shù)調(diào)用的時(shí)候求值一 次,它的結(jié)果值傳遞給函數(shù)。表達(dá)式 的求值結(jié)果更容易預(yù)測(cè)。
帶 有 副 作 用 的 參 數(shù) 參數(shù)可能被替換到宏體中的多個(gè)位置,所以帶有副作用的參 數(shù)求值可能會(huì)產(chǎn)生不可預(yù)料的結(jié)果。 函數(shù)參數(shù)只在傳參的時(shí)候求值一次, 結(jié)果更容易控制。
參 數(shù) 類 型 宏的參數(shù)與類型無關(guān),只要對(duì)參數(shù)的操作是合法的,它就可 以使用于任何參數(shù)類型。 函數(shù)的參數(shù)是與類型有關(guān)的,如果參 數(shù)的類型不同,就需要不同的函數(shù), 即使他們執(zhí)行的任務(wù)是不同的
調(diào) 試 宏是不方便調(diào)試的 函數(shù)是可以逐語句調(diào)試的
遞 歸 宏是不能遞歸的 函數(shù)是可以遞歸的

四,命名約定

一般來講函數(shù)的宏的使用語法很相似。所以語言本身沒法幫我們區(qū)分二者。 那我們平時(shí)的一個(gè)習(xí)慣是:

把宏名全部大寫 函數(shù)名不要全部大寫

1,#undef

這條指令用于移除一個(gè)宏定義。

#undef NAME 
//如果現(xiàn)存的一個(gè)名字需要被重新定義,那么它的舊名字首先要被移除。

命令行定義

許多C 的編譯器提供了一種能力,允許在命令行中定義符號(hào)。用于啟動(dòng)編譯過程。 例如:當(dāng)我們根據(jù)同一個(gè)源文件要 編譯出不同的一個(gè)程序的不同版本的時(shí)候,這個(gè)特性有點(diǎn)用處。(假定某個(gè)程序中聲明了一個(gè)某個(gè)長(zhǎng)度的數(shù)組,如果 機(jī)器內(nèi)存有限,我們需要一個(gè)很小的數(shù)組,但是另外一個(gè)機(jī)器內(nèi)存大寫,我們需要一個(gè)數(shù)組能夠大寫。)

#define	MAX 100
 int main()
{
	int m = MAX;
    #undef MAX
	int n = MAX;//err
	return 0;
}
#define M 500
 int main()
{
#if M==100
	printf("haha\n");
#elif M==200
	printf("hehe\n");
#else
	printf("heihei\n");
#endif
 	return 0;
}

2,文件包含

我們已經(jīng)知道, #include 指令可以使另外一個(gè)文件被編譯。就像它實(shí)際出現(xiàn)于 #include 指令的地方一樣。 這種替換的方式很簡(jiǎn)單: 預(yù)處理器先刪除這條指令,并用包含文件的內(nèi)容替換。 這樣一個(gè)源文件被包含10次,那就 實(shí)際被編譯10次。

頭文件被包含的方式:

#include "filename" 

VS環(huán)境的標(biāo)準(zhǔn)頭文件的路徑:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include

庫文件包含

#include <filename.h>

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • C++面向行輸入之get()與getline()實(shí)例詳解

    C++面向行輸入之get()與getline()實(shí)例詳解

    在c++里當(dāng)我們輸入一個(gè)字符串時(shí)習(xí)慣用cin,但是cin只能讀取一段不含空格的字符串,如果我們需要讀取一段包含空格的字符串時(shí),就需要用到getline()或get(),下面這篇文章主要給大家介紹了關(guān)于C++面向行輸入之get()與getline()的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • C語言實(shí)現(xiàn)文件讀寫功能流程

    C語言實(shí)現(xiàn)文件讀寫功能流程

    這篇文章主要介紹了C語言實(shí)現(xiàn)文件讀寫,文件是一段數(shù)據(jù)的集合,這些數(shù)據(jù)可以是有規(guī)則的,也可以是無序的集合。在stdio.h有一個(gè)非常重要的東西,文件指針,每個(gè)文件都會(huì)在內(nèi)存中開辟一塊空間,用于存放文件的相關(guān)信息
    2022-12-12
  • 深入了解c++數(shù)組與指針

    深入了解c++數(shù)組與指針

    這篇文章主要介紹了c++數(shù)組與指針的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • C語言掃雷詳細(xì)代碼分步實(shí)現(xiàn)流程

    C語言掃雷詳細(xì)代碼分步實(shí)現(xiàn)流程

    掃雷是電腦上很經(jīng)典的游戲,特意去網(wǎng)上玩了一會(huì),幾次調(diào)試之后,發(fā)現(xiàn)這個(gè)比三子棋要復(fù)雜一些,尤其是空白展開算法上和堵截玩家有的一拼,與實(shí)際游戲差別較大,不能使用光標(biāo),下面來詳解每一步分析
    2022-02-02
  • 一文搞懂Codec2解碼組件

    一文搞懂Codec2解碼組件

    這篇文章主要介紹了Codec2解碼組件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • C++?MiniZip實(shí)現(xiàn)目錄壓縮與解壓的示例詳解

    C++?MiniZip實(shí)現(xiàn)目錄壓縮與解壓的示例詳解

    Zlib是一個(gè)開源的數(shù)據(jù)壓縮庫,提供了一種通用的數(shù)據(jù)壓縮和解壓縮算法,本文主要為大家詳細(xì)介紹了如何利用Zlib實(shí)現(xiàn)目錄壓縮與解壓,需要的小伙伴可以參考下
    2023-11-11
  • C++入門到精通之循環(huán)語句的使用教程

    C++入門到精通之循環(huán)語句的使用教程

    這篇文章主要給大家介紹了關(guān)于C++中循環(huán)語句的用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • C語言修煉之路數(shù)據(jù)類型悟正法 解析存儲(chǔ)定風(fēng)魔下篇

    C語言修煉之路數(shù)據(jù)類型悟正法 解析存儲(chǔ)定風(fēng)魔下篇

    使用編程語言進(jìn)行編程時(shí),需要用到各種變量來存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么
    2022-02-02
  • C++小游戲教程之猜數(shù)游戲的實(shí)現(xiàn)

    C++小游戲教程之猜數(shù)游戲的實(shí)現(xiàn)

    這篇文章主要和大家詳細(xì)介紹如何利用C++做一個(gè)簡(jiǎn)易的猜數(shù)游戲,分為用戶猜數(shù)和系統(tǒng)猜數(shù)。文中的示例代碼講解詳細(xì) ,感興趣的小伙伴可以嘗試一下
    2022-11-11
  • 一起來學(xué)習(xí)C++的動(dòng)態(tài)內(nèi)存管理

    一起來學(xué)習(xí)C++的動(dòng)態(tài)內(nèi)存管理

    這篇文章主要為大家詳細(xì)介紹了C++的動(dòng)態(tài)內(nèi)存管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03

最新評(píng)論

大同市| 凭祥市| 清河县| 江口县| 威宁| 扶余县| 潜山县| 汝城县| 百色市| 绥宁县| 新乡市| 汤阴县| 依安县| 蒙城县| 漯河市| 宁化县| 长兴县| 普兰店市| 德州市| 巩义市| 通榆县| 澄江县| 霞浦县| 手游| 龙川县| 军事| 古田县| 兴义市| 克东县| 始兴县| 大名县| 山东省| 安达市| 当雄县| 海阳市| 永平县| 绍兴县| 浪卡子县| 井冈山市| 民乐县| 湖州市|