作者的碼云地址:https://gitee.com/dongtiao-xiewei
后續作者會更新力扣的每日一題系列,原代碼會全部上傳碼云,推薦關注哦,筆芯~
還像更深入地了解c語言?快來訂閱作者的c語言進階專欄!作者承諾本系列不會TJ!預計更新:指標,字串處理,記憶體管理,結構體,預處理等等
感謝朋友們的支持,我們這個系列今天終于完結啦!
我們一直以來寫的代碼,本質其實都是以.c檔案為后綴名的文本檔案,例如我們隨便以記事本形式點來一個.c后綴的檔案

點開我們看到,就是我們熟悉的代碼樣式
但這就有一個問題,這種文本檔案是如何被計算機識別的呢?
其實計算機能夠識別的就只有機器語言,也就是一串二進制代碼,早期的程式員也是全用機器語言編程,后面為了避免麻煩,簡化編程的程序,就產生了較為容易理解匯編語言,而匯編程序就是將匯編語言轉化為機器語言
而為了解決平臺的可移植性和通用性的問題,又產生了高級語言,例如c語言,basic語言等,而編譯程序,可把高級語言轉化為匯編語言
所以,現代計算機可分為以下幾個層次

我們的c代碼若要生成一個可執行程式(二進制代碼)需要進行以下幾個步驟

今天的章節我們重點介紹預處理環節
預處理環節將會進行以下作業
- 處理define定義好的識別符號,宏等
- 去掉注釋
我們可以先測驗一下去掉注釋
int main()
{
printf("hello world!\n");//you can see me!
return 0;
}
預處理后的結果:

注:由于VS編譯器查看預處理后的代碼比較困難,所以本章節的代碼我們使用linux平臺測驗
本節用到的linux指令:
touch test.c創建一個源檔案
vim test.c 撰寫代碼
gcc -E test.c -o test.i 將預處理后的代碼保存在test.i中
好,坐穩扶好,我們正式開始嘍!
目錄
- #define
- #define定義識別符號
- #define定義宏
- 條件編譯
- #ifdef
- ifndef
- #if
#define
#define定義識別符號
通用格式:
#define name stuff
例子:
#define MAX 200
#define str struct
我們用這個定義識別符號可以起到定義常量,重命名,同名替換等等
可以在linux上簡單測驗一下
#define MAX 200
#define reg register
int main()
{
reg int a=MAX;
printf("%d\n",a);
return 0;
}

而代碼也能跑的過去

我們可以看到,預處理階段就完成了簡單替換
萌新最容易犯的錯誤:在定義完成后加上’’;’'
#define MAX 200;
雖然這個代碼可能在有些情況不會出錯,但替換下來就是這個結果

看起來很奇怪,是吧!
#define定義宏
這是define的一個特殊機制,允許把引數替換在文本中
例子
#define DOUBLE(x) (x+x)
通用格式
#define name(list) stuff
宏的使用

雖然是宏,但我們可以觀察到,本質也是簡單替換

我們同樣也可以定義以下的宏
#define SQUARE(x) x*x
但是注意,這個宏存在一個問題,假如我們要算這個運算式的結果
SQUARE(5+1)
我們期望結果當然是6的平方,也就是36
但是我們測驗發現結果并不是36

結果居然是11!
我們可以打開test.i檔案查看一下預處理后的代碼

我們可以發現,宏僅僅只是完成了簡單替換,并沒有考慮優先級的問題
這個其實就是根據替換后的算術優先級來計算結果
1*5=5+5+1=11
當然,為了避免算術優先級的問題,我們可以對代碼做一點改進
#define SQUARE(x) ((x)*(x))
這樣修改后,宏就會是相對獨立的運算結果了

條件編譯
在編譯一個程式的時候我們如果要將一條陳述句(一組陳述句)編譯或者放棄是很方便的,因為我們有條件編譯指令,
有以下條件編譯指令
#ifdef,#ifndef,#if等等
注意,條件編譯的末尾一定要加上#endif!
#ifdef
只有你編譯了某個宏,代碼才會被執行
比如我們在要除錯一個代碼的場景


這里顯示了列印字符,如果我們把它注釋掉,就不會顯示
ifndef
同樣還是上面的代碼,但是卻與上面功能相反
沒有定義,才執行下列的程式
應用場景:頭檔案防止被重復包含
#ifndef __TEST_H__
#define __TEST_H__
//代碼
#endif
#if
與分支陳述句的if相同,例如


轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/312172.html
標籤:其他
