C語言深度解剖讀書筆記 3 預編譯處理

2021-08-27 14:31:18 字數 2685 閱讀 6549

1.編譯過程的簡介:

預編譯:

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

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

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

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

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

怎麼樣觀察這些變化呢?最好的方法就是在gcc中,輸入預處理指令,可以看看不同檔案經過預處理後變成什麼樣了,預處理指令:gcc -e file.c -o file.i 注意:-c -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 file.c -ofile

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的例子:

#include #include #include #define x 2

#define y x*2

#undef x

#define x 3

int main()

這個輸出的是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這個#號必須使用在帶參巨集中

有個小例子:

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

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

int main()

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

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

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

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

#include #include #include #define bl1 bb##ll##1

#define bl(n) bbll##n

int main()

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

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

C語言深度解剖讀書筆記 3 預編譯處理

1.編譯過程的簡介 預編譯 a.處理所有的注釋,以空格代替。b.將所以 define刪除,並展開所有的巨集定義,字串替換。c.處理條件編譯指令 if,ifdef,elif,else,endif d.處理 include,並展開被包含的檔案,把頭檔案中的宣告,全部拷貝到檔案中。e.保留編譯器需要使用的...

C語言深度解剖讀書筆記3

int p null 和 p null 的區別int p null 可以通過偵錯程式檢視p的值為 0x00000000 這句 的意思是 定義乙個指標變數p,其指向的記憶體裡面儲存的是 int 型別的資料 在定義變數p的同時把p的值設定為 0x00000000,而不是把 p 的值設定為0x000000...

讀書筆記《c語言深度解剖》 4

10.struct關鍵字 這裡struct關鍵字講解得比較少,主要有3點 1 空結構體的大小為1 在gcc下我的輸出是0 2 柔性陣列 在c99中,允許結構最後乙個元素是乙個大小未確定的陣列,這個陣列叫做柔性陣列。但是柔性陣列前面必須至少有乙個其他成員。用sizeof返回結構體大小的時候,並不包含柔...