日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ios c语言头文件,iOS开发 -- C语言基础12(预处理指令)

發布時間:2025/3/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ios c语言头文件,iOS开发 -- C语言基础12(预处理指令) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

iOS開發 -- C語言基礎12(預處理指令)

宏定義

預處理指令簡介

1.C語言在對源程序進行編譯之前,會先對一些特殊的預處理指令作解釋(比如之前使用的#include文件包含指令),產生一個新的源程序(這個過程稱為編譯預處理),之后再進行通常的編譯

2.為了區分預處理指令和一般的C語句,所有預處理指令都以符號"#"開頭,并且結尾不用分號

3.預處理指令可以出現在程序的任何位置,它的作用范圍是從它出現的位置到文件尾。習慣上我們盡可能將預處理指令寫在源程序開頭,這種情況下,它的作用范圍就是整個源程序文件

4.C語言提供的預處理指令主要有:宏定義、文件包含、條件編譯

這一講先介紹一下宏定義,宏定義可以分為2種:不帶參數的宏定義 和 帶參數的宏定義。

一、不帶參數的宏定義

1.一般形式

#define 宏名 字符串

比如#define ABC 10

右邊的字符串也可以省略,比如#define ABC

2.作用

它的作用是在編譯預處理時,將源程序中所有"宏名"替換成右邊的"字符串",常用來定義常量。

接下來寫個程序根據圓的半徑計算周長#include

// 源程序中所有的宏名PI在編譯預處理的時候都會被3.14所代替

#define PI 3.14

// 根據圓的半徑計radius算周長

float girth(float radius) {

return 2 * PI *radius;

}int main ()

{

float g = girth(2);

printf("周長為:%f", g);

return 0;

}

在第4行定義了一個叫PI的宏,在編譯預處理之后,第8行中的2 * PI *radius就會變成2 * 3.14 * radius。

輸出結果:

3.使用習慣與注意

1> 宏名一般用大寫字母,以便與變量名區別開來,但用小寫也沒有語法錯誤

2> 對程序中用雙引號擴起來的字符串內的字符,不進行宏的替換操作。比如:#define R 10

int main ()

{

char *s = "Radio";

return 0;

}

在第1行定義了一個叫R的宏,但是第4行中"Radio"里面的'R'并不會被替換成10

3> 在編譯預處理用字符串替換宏名時,不作語法檢查,只是簡單的字符串替換。只有在編譯的時候才對已經展開宏名的源程序進行語法檢查#define I 100

int main ()

{

int i[3] = I;

return 0;

}

在做編譯預處理的時候,不管語法對不對,第4行的I都會被替換為100。不過在編譯的時候就會報第4行的錯。

4> 宏名的有效范圍是從定義位置到文件結束。如果需要終止宏定義的作用域,可以用#undef命令#define PI 3.14

/*

.

.

.

.

*/

#undef PI

PI這個宏在第1行到第8行之間是有效的,第8行后就無效了

5> 定義一個宏時可以引用已經定義的宏名#define R? 3.0

#define PI 3.14

#define L? 2*PI*R

#define S? PI*R*R

二、帶參數的宏定義

1.一般形式

#define 宏名(參數列表) 字符串

2.作用

在編譯預處理時,將源程序中所有宏名替換成字符串,并且將 字符串中的參數 用 宏名右邊參數列表 中的參數替換#include

#define average(a, b) (a+b)/2

int main ()

{

int a = average(10, 4);

printf("平均值:%d", a);

return 0;

}

第3行中定義了一個帶有2個參數的宏average,第7行其實會被替換成:int a = (10 + 4)/2;,輸出結果為:

。是不是感覺這個宏有點像函數呢?

3.使用注意

1> 宏名和參數列表之間不能有空格,否則空格后面的所有字符串都作為替換的字符串#define average (a, b) (a+b)/2

int main ()

{

int a = average(10, 4);

return 0;

}

注意第1行的宏定義,宏名average跟(a, b)之間是有空格的,于是,第5行就變成了這樣:

int a = (a, b) (a+b)/2(10, 4);

這個肯定是編譯不通過的

2> 帶參數的宏在展開時,只作簡單的字符和參數的替換,不進行任何計算操作。所以在定義宏時,一般用一個小括號括住字符串的參數。

下面定義一個宏D(a),作用是返回a的2倍數值:

如果定義宏的時候不用小括號括住參數#include

#define D(a) 2*a

int main ()

{

int b = D(3+4);

printf("%d", b);

return 0;

}

第7行將被替換成int b = 2*3+4;,輸出結果:

如果定義宏的時候用小括號括住參數,把上面的第3行改成:#define D(a) 2*(a)

注意右邊的a是有括號的,第7行將被替換成int b = 2*(3+4);,輸出結果:

3> 計算結果最好也用括號括起來

下面定義一個宏P(a),作用是返回a的平方:#include

#define Pow(a) (a) * (a)

int main(int argc, const char * argv[]) {

int b = Pow(10) / Pow(2);

printf("%d", b);

return 0;

}

注意第3行,沒有用小括號擴住計算結果,只是括住了參數而已。第6行代碼被替換為:int b = (10) * (10) / (2) * (2);

簡化之后:int b = 10 * (10 / 2) * 2;,最后變量b為:

如果用小括號括住計算結果

將上面的第3行代碼改為:#define Pow(a) ( (a) * (a) )

那么第6行被替換為:int b = ( (10) * (10) ) / ( (2) * (2) );

簡化之后:int b = (10 * 10) / (2 * 2);,最后輸出結果:。這個才是我們想要的結果。

也就意味著前面的#define average(a, b) (a+b)/2應該寫成#define average(a, b) (((a)+(b))/2)

5.與函數的區別

從整個使用過程可以發現,帶參數的宏定義,在源程序中出現的形式與函數很像。但是兩者是有本質區別的:

1> 宏定義不涉及存儲空間的分配、參數類型匹配、參數傳遞、返回值問題

2> 函數調用在程序運行時執行,而宏替換只在編譯預處理階段進行。所以帶參數的宏比函數具有更高的執行效率

條件編譯

條件編譯的概念

在很多情況下,我們希望程序的其中一部分代碼只有在滿足一定條件時才進行編譯,否則不參與編譯(只有參與編譯的代碼最終才能被執行),這就是條件編譯。

一、基本用法#if 條件1

...code1...

#elif 條件2

...code2...

#else

...code3...

#endif

1> 如果條件1成立,那么編譯器就會把#if 與 #elif之間的code1代碼編譯進去(注意:是編譯進去,不是執行,很平時用的if-else是不一樣的)

2> 如果條件1不成立、條件2成立,那么編譯器就會把#elif 與 #else之間的code2代碼編譯進去

3> 如果條件1、2都不成立,那么編譯器就會把#else 與 #endif之間的code3編譯進去

4> 注意,條件編譯結束后,要在最后面加一個#endif,不然后果很嚴重(自己思考一下后果)

5> #if 和 #elif后面的條件一般是判斷宏定義而不是判斷變量,因為條件編譯是在編譯之前做的判斷,宏定義也是編譯之前定義的,而變量是在運行時才產生的、才有使用的意義

二、舉個例子#include

#define MAX 11

int main ()

{

#if MAX == 0

printf("MAX是0");

#elif MAX > 0

printf("MAX大于0");

#else

printf("MAX小于0");

#endif

return 0;

}

在第3行定義了一個宏MAX,當然在開發中這個MAX可能被定義在其他頭文件中,現在只是為了方便演示,就寫到main函數上面了。注意第7到第13行的條件編譯語句。

由于MAX為11,所以#elif的條件成立,第10行代碼將會被編譯進去,其實編譯預處理后的代碼是這樣的:/*stdio.h文件中的內容將會代替#include的位置*/

int main ()

{

printf("MAX大于0");

return 0;

}

代碼變得非常簡潔,輸出結果:

三、其他用法

1.#if defined()和#if !defined()的用法

#if 和 #elif后面的條件不僅僅可以用來判斷宏的值,還可以判斷是否定義過某個宏。比如:

#if defined(MAX)

...code...

#endif

如果前面已經定義過MAX這個宏,就將code編譯進去。它不會管MAX的值是多少,只要定義過MAX,條件就成立。

條件也可以取反:

#if !defined(MAX)

...code...

#endif

如果前面沒有定義過MAX這個宏,就將code編譯進去。

2.#ifdef和#ifndef的使用

* #ifdef的使用和#if defined()的用法基本一致

#ifdef MAX

...code...

#endif

如果前面已經定義過MAX這個宏,就將code編譯進去。

* #ifndef又和#if !defined()的用法基本一致

#ifndef MAX

...code...

#endif

如果前面沒有定義過MAX這個宏,就將code編譯進去。

文件包含

一、基本概念

其實我們早就有接觸文件包含這個指令了, 就是#include,它可以將一個文件的全部內容拷貝另一個文件中。

二、一般形式

1.第1種形式#include 

直接到C語言庫函數頭文件所在的目錄中尋找文件

2.第2種形式 #include "文件名"

系統會先在源程序當前目錄下尋找,若找不到,再到操作系統的path路徑中查找,最后才到C語言庫函數頭文件所在目錄中查找

三、使用注意

1.#include指令允許嵌套包含,比如a.h包含b.h,b.h包含c.h,但是不允許遞歸包含,比如 a.h 包含 b.h,b.h 包含 a.h。

下面的做法是錯誤的

2.使用#include指令可能導致多次包含同一個頭文件,降低編譯效率

比如下面的情況:

在one.h中聲明了一個one函數;在two.h中包含了one.h,順便聲明了一個two函數。(這里就不寫函數的實現了,也就是函數的定義)

假如我想在main.c中使用one和two兩個函數,而且有時候我們并不一定知道two.h中包含了one.h,所以可能會這樣做:

編譯預處理之后main.c的代碼是這樣的:void one();

void one();

void two();

int main ()

{

return 0;

}

第1行是由#include "one.h"導致的,第2、3行是由#include "two.h"導致的(因為two.h里面包含了one.h)。可以看出來,one函數被聲明了2遍,根本就沒有必要,這樣會降低編譯效率。

為了解決這種重復包含同一個頭文件的問題,一般我們會這樣寫頭文件內容:

大致解釋一下意思,就拿one.h為例:當我們第一次#include "one.h"時,因為沒有定義_ONE_H_,所以第9行的條件成立,接著在第10行定義了_ONE_H_這個宏,然后在13行聲明one函數,最后在15行結束條件編譯。當第二次#include "one.h",因為之前已經定義過_ONE_H_這個宏,所以第9行的條件不成立,直接跳到第15行的#endif,結束條件編譯。就是這么簡單的3句代碼,防止了one.h的內容被重復包含。

這樣子的話,main.c中的:#include "one.h"

#include "two.h"

就變成了:// #include "one.h"

#ifndef _ONE_H_

#define _ONE_H_

void one();

#endif// #include "two.h"

#ifndef _TWO_H_

#define _TWO_H_

// #include "one.h"

#ifndef _ONE_H_

#define _ONE_H_

void one();

#endifvoid two();

#endif

第2~第7行是#include "one.h"導致的,第10~第23行是#include "two.h"導致的。編譯預處理之后就變為了:void one();

void two();

這才是我們想要的結果。

總結

以上是生活随笔為你收集整理的ios c语言头文件,iOS开发 -- C语言基础12(预处理指令)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本高清视频www夜色资源 | 亚洲最新色图 | 久久久久久国产精品免费免费 | 亚洲25p| 国产第3页 | 午夜免费体验区 | 日韩精品一区二区不卡 | 久久靠逼视频 | 久久香蕉影院 | 亚洲熟妇av一区二区三区漫画 | 日本熟妇一区二区三区 | 在线网站av | 亚洲第一精品在线 | 极品蜜桃臀肥臀-x88av | 成人午夜福利视频 | 熟女性饥渴一区二区三区 | 国产第4页 | 搡老岳熟女国产熟妇 | 午夜精品久久久久久久99老熟妇 | 伊人影院在线观看 | 理论片中文字幕 | 亚洲日本激情 | 成人动漫一区 | 国产精品66 | 欧美天堂网站 | 午夜影院a | 亚洲免费精品视频 | 亚洲裸体网站 | 欧美精品三级 | 国产大尺度视频 | 午夜视频在线观看一区二区 | 亚洲熟女www一区二区三区 | 黑人一区二区三区四区五区 | 中文字幕一区二区三区人妻在线视频 | 99综合在线| 四虎免费视频 | aaa大片十八岁禁止 中文字幕亚洲在线观看 | 国产噜噜噜噜久久久久久久久 | 日韩网站在线 | 黄色三级小说 | 亚洲综合在线一区 | 丁香在线视频 | 91久久一区 | 欧美丝袜一区二区三区 | 欧美精品久久久久性色 | 偷偷操不一样的久久 | 国产成人高清 | 久热国产在线 | a中文字幕| 国产乱子伦视频一区二区三区 | 欧美乱妇日本无乱码特黄大片 | 粉嫩av一区二区三区免费观看 | 少妇又紧又深又湿又爽视频 | 日韩免费影视 | 在线免费观看成年人视频 | 国产露脸91国语对白 | 99久久久久无码国产精品 | 国产成人精品一区二区三区网站观看 | 色婷婷狠狠18禁久久 | 欧美精品一二三 | 91精品毛片 | 精品在线播放视频 | 各种含道具高h调教1v1男男 | 日韩中文一区二区 | 国产精品网友自拍 | 在线观看一级片 | 国产精品久久久久久久久久久久久久久 | 黄色资源在线 | 日韩美av| 亚洲第一成年人网站 | 欧美黑人精品 | 国产精品日韩电影 | 欧美激情一区二区三区p站 欧美mv日韩mv国产网站app | 精品人妻天天爽夜夜爽视频 | 三级网站在线看 | 男男全肉变态重口高h | 免费中文视频 | 精品无码av一区二区三区不卡 | 狠狠做深爱婷婷综合一区 | 色爱av综合 | 热久久精品免费视频 | 女同一区二区 | 欧美男人天堂 | 日日干日日摸 | 久久久精品国产 | 波多野在线播放 | 久伊人网 | 国产欧美在线看 | 男女午夜激情 | 91福利社在线观看 | 久久接色 | av免费精品| 懂爱av | 黄色片上床 | 妹子色综合 | 五月婷婷六月综合 | 狠狠网| 伊人中文在线 | 黄色高潮 |