預編譯處理

2021-07-02 04:42:20 字數 3092 閱讀 9138

1.編譯過程的簡介:

預編譯:

a.處理所有的注釋,以空格代替。

b.將所有#define刪除,並展開所有的巨集定義,字串替換。

c.處理條件編譯指令#if,#ifdef,#elif,#else,#endif

d.處理#include,並展開被包含的檔案,把頭檔案中的宣告,全部拷貝到檔案中。

e.保留編譯器需要使用的#pragma指令、

gcc file.c -o file.i -e生成預處理過的檔案

編譯:

a.對預處理檔案進行一系列詞法分析,語法分析和語義分析

詞法分析:主要分析關鍵字,標示符,立即數等是否合法

語法分析:主要分析表示式是否遵循語法規則

語義分析:在語法分析的基礎上進一步分析表示式是否合法

b.分析結束後進行**優化生成相應的彙編**檔案               編譯指令:gcc -s  file.c  -o  file.s

彙編:彙編器將彙編**轉變為機器可以執行的指令,每個彙編語句幾乎都對應一條機器指令,其實機器指令就是機器碼,就是2進製碼。彙編指令:gcc  -c  file.c  -o file.o  注意:-c是編譯彙編不連線。

再把產生的.o檔案,進行鏈結就可以生成可執行檔案。連線指令:gcc  file.o  file1.o  -o  file  這句指令是鏈結file.o和file1.o兩個編譯並彙編的檔案,並生成可執行檔案file。

鏈結分兩種:靜態鏈結和動態鏈結,靜態鏈結是在編譯器完成的,動態鏈結是在執行期完成的。靜態鏈結的指令是:gcc -static file.c -o file對於一些沒有動態庫的嵌入式系統,這是常用的。

一般要想通過一條指令生成可執行檔案的指令是:   gcc file.c  -o  file

2.c語言中的預處理指令:#define、#undef(撤銷已定義過的巨集名)、#include、#if、#else、#elif、#endif、#ifdef、#ifndef、#line、#error、#pragma。還有一些ansi標準c定義的巨集:__line__、__file__、__data__、__time__、__stdc__。這樣使用printf("%s\n",__time__);     printf(__date__);

乙個#undef的例子:

[cpp]view plain

copy

#include 

#include 

#include 

#define x 2

#define y x*2

#undef x

#define x 3

intmain()    

這個輸出的是6,說明了#undef的作用

3.巨集定義字串的時候:應該是 #define hello "hello world"  記住是雙引號。還有就是一切巨集都是不能有分號的,這個一定要切忌!!!

4.巨集與函式的比較:

a.巨集表示式在預編譯期被處理,編譯器不知道有巨集表示式存在

b.巨集表示式沒有任何的"呼叫"開銷

c.巨集表示式中不能出現遞迴定義

5.為什麼不在標頭檔案中定義全域性變數:

如果乙個全域性變數,想要在兩個檔案中,同時使用,那這兩個檔案中都應該#include這個標頭檔案,這樣的話就會出現重複定義的問題。其實是重名的問題,因為#include是分別在兩個檔案中展開的,試想一下,如果在兩個檔案中的開始部分,都寫上int  a = 10;  是不是也會報錯。可能你會說那個#ifndef不是防止重複定義嗎?是的 ,那是防止在同乙個檔案中,同時出現兩次這個標頭檔案。現在是兩個檔案中,所以都要展開的。全域性變數就重名了!!!所以 對於全域性變數,最好是定義在.c檔案中,不要定義在標頭檔案中。

6.#pargma pack 設定字元對齊,看後面一節專門寫字元對齊問題的!!!

7.#運算子**換成字串):

假如你希望在字串中包含巨集引數,那我們就用#號,它把語言符號轉換成字串。

#define sqr(x) printf("the "#x"lait %d\n",((x)*(x)));

sqr(8)

輸出結果是:the 8 lait 64這個#號必須使用在帶參巨集中

有個小例子:

[cpp]view plain

copy

#include 

#include 

#include 

/*在字串中  加入巨集參用的*/

#define scan(n,string) scanf("%"#n"s",string);  //n是擷取的個數  string是儲存的字串 

intmain()    

8.##運算子(粘合劑)

一般用於貼上兩個東西,一般是用作在給變數或函式命名的時候使用。如#define xname(n) x##n

xname(8)為8n這個##號可以使用在帶參巨集或無參巨集中

下面是乙個##運算子的小例子,**如下:

[cpp]view plain

copy

#include 

#include 

#include 

#define bl1 bb##ll##1

#define bl(n) bbll##n

intmain()    

注意:#號和##號都必須只能在巨集定義中使用,不能使用在其他地方

9.其實預編譯這塊還有一些,不常用到的預編譯指令,也是盲點,但是不難理解,用到的時候查查就好。比如說#line、#error、#warning等。

stdafx h預編譯處理

stdafx.h中沒有函式庫,只是定義了一些環境引數,使得編譯出來的程式能在32位的作業系統環境下執行。windows和mfc的include檔案都非常大,即使有乙個快速的處理程式,編譯程式也要花費相當長的時間來完成工作。由於每個.cpp檔案都包含相同的include檔案,為每個.cpp檔案都重複處...

預編譯處理命令

if endif是c 種的條件編譯預處理命令 有兩種格式 1 ifdef 標示符 程式段1 else 程式段2 endif 表示 如果標示符已經被 define命令定義過,則編譯程式段1,否則編譯程式段2 2 if 表示式 程式段1 else 程式段2 endif 表示 如果表示式為真,則編譯程式段...

c 預編譯處理

定義 預編譯又稱為預處理 是做些 文字的替換工作。處理 開頭的指令 比如拷貝 include 包含的檔案 define 巨集定義的替換 條件編譯等,就是為編譯做的預備工作的階段,主要處理 開始的預編譯指令,預編譯指令指示了在程式正式編譯前就由編譯器進行的操作,可以放在程式中的任何位置,其存放在記憶體...