十五.編譯過程
file.c,file.h經過預處理器處理成為file.i,再經過編譯器(gcc)成為彙編file.s,再經過彙編器(as)成為file.o,最後通過聯結器(linker)成為可執行檔案。
預處理器:1.處理所有的注釋,以空格代替
2.將所有的#define刪除,並展開所有定義的巨集
3.處理條件編譯指令,#if,#ifdef,#elif,#else,#endif
4.處理#include,展開被包含的檔案
5.保留編譯器需要使用的#pragma指令
指令為:gcc -e file.c -o hello.i,得到預處理器處理完後的檔案
編譯器: 對預處理檔案進行一系列的詞法分析,語法分析,和語義分析,分析結束後進行**優化,生成相應的彙編**
指令為:gcc -s file.c -o hello.s
彙編器:將彙編**轉變成為可執行的指令。
指令為:gcc -c file.s -o hello.o
聯結器:把各個模組之間相互引用的部分處理好,使得各個模組之間能夠正確的銜接,靜態鏈結在編譯期完成,動態鏈結在執行期完成。
十六.巨集定義與使用分析
巨集可以定義在**的任何地方,之後的**都可以使用。
巨集表示式與函式的對比:
1.巨集表示式在預編譯器被處理(單純的展開),編譯器不知道巨集表示式的存在
2.巨集表示式用「實參」完全代替形參,不進行任何運算,任何字元都可以替換,應用更廣
3. 巨集表示式沒有任何呼叫開銷
4.巨集表示式中不能出現遞迴定義
個巨集比乙個巨集比函式強的例子:
#define dim(array) (sizeof(array)/sizeof(*array))第乙個array代表陣列
int dim(int array)
在這個求陣列長度的例子中,巨集由於是直接替換,所以沒問題,但是陣列名做函式引數直接就會退化成為指標,返回值就不正確了(指標所佔位數/陣列第乙個元素的記憶體位數,32位返回1,64位返回2)。
內建巨集:
十七.條件編譯使用分析
可以在進行編譯的時候指定程式需要使用的巨集定義,來進行預處理展開,-d定義巨集 -u取消巨集
#include 本質是將檔案內容嵌入當前檔案,所以被包含的檔案應當使用#ifndef……#define……#endif,防止重複包含
十八.#error和#line指示字
#error用於生成乙個編譯錯誤訊息,並停止編譯
用法:#error message(message不需要雙引號)
#warning類似作用
#line 用於強制指定新的行號和編譯檔名,並對源程式的**重新編號,新的行號從下一行開始。用於指定自己的**,現在可以用更先進的版本控制以及靜態庫和動態庫來解決多人編碼
用法:#line number filename(filename可以省略)
十九.#pragma預處理分析
#pragma是編譯器指示字,用於指示編譯器完成一些特定的動作。
#pragma 所定義的很多指示字是編譯器和作業系統特有的,在不同的編譯器間是不可移植的
#pragma: 預處理器會忽略不認識的#pragma指令並刪除,並將認識的指令留給編譯器來處理
#pragma message:編譯時輸出訊息到編譯輸出視窗,可用於**的版本控制,vc特有,gcc將會忽略
記憶體對齊:
為什麼:cpu對記憶體讀取不是連續的,而是分塊讀取的,塊的大小只能是1,2,4,8,16位元組
當讀取操作的資料未對齊,則需要兩次匯流排週期來訪問記憶體,因此效能會大打折扣
某些硬體平台只能從規定的位址處取某些特定型別的資料,否則會丟擲硬體異常
#pragma pack能夠改變編譯器的預設對齊方式
struct占用記憶體大小計算方法:
gcc預設為4個位元組對齊
不能使用memcmp函式判斷結構體是否相等,因為memcmp是使用記憶體進行判斷,結構體使用前不清零,即使重新賦相同的值,每個記憶體位址裡的值也不一定相同,另外乙個原因就是因為對齊,有些記憶體位址是未定義的。
二十.#和##運算子
#運算子是預處理指令開始符,比如#include<>
#運算子用於在預編譯期將巨集引數轉換為字串
#include #define convers(x) #x
int main()
輸出結果:hello world!
100while
return
##用於在預編譯期粘連兩個符號
#include #define name(n) name##n
int main()
輸出:12
預處理器把name(1)替換成name1,name(2)替換成name2
用處:定義結構體型別。
#include #define struct(type) typedef struct _tag_##type type;\
struct _tag_##type
struct(student)
;int main()
高效整潔的定義結構體,用於高通平台。 C語言要點
一關鍵字 1.static 第乙個作用 修飾變數。變數又分為區域性和全域性變數,但它們都存在記憶體的靜態區。由於被static修飾的變數總是存在記憶體的靜態區,所以即使這個函式執行結束,這個靜態變數的值還是不會被銷毀,函式下次使用時仍然能用到這個值。static int j void fun1 vo...
PostgreSQL修煉之道要點摘錄
6.1表空間 有時我們需要把不同的表放到不同的儲存介質或不同的檔案系統下,這時就需要使用表空間。6.9索引 b tree索引 最常用的索引適合處理等值查詢和範圍查詢 hash索引 只能處理簡單的等值查詢 其它索引 gist sp gist gin 6.11事務 併發 鎖 a.事務的四個特性acid,...
C語言解惑要點
1 運算子的優先順序 2 型別轉換 2.1 有符號與無符號數 結果輸出為 2 2 1 2147483647 1 2147483647 2.2 浮點數與整數 3 控制流 這一部分主要需要注意if else之間的巢狀時的配對情況,及迴圈語句的終止條件與狀態。4 轉義字元 除了 n t這一類的轉義字元,還...