預處理與結構體

2021-08-09 17:34:51 字數 2750 閱讀 8758

巨集定義、檔案包含、條件編譯
1、 巨集定義不是說明或語句,不需要在結尾加上分號

2、巨集定義必須寫在函式之外,其作用域是巨集定義命令起到源程式結束,如需要終止可使用#undef命令

3、預處理程式不對巨集定義做任何檢查,如有錯誤,只能在編譯被巨集定義展開後的源程式時發現

1、巨集會在編譯器在對源**進行編譯的時候進行簡單替換,不會進行任何邏輯檢測,即簡單**複製而已。

2、巨集進行定義時不會考慮引數的型別。

3、引數巨集的使用會使具有同一作用的**塊在目標檔案中存在多個副本,即會增長目標檔案的大小。

4、引數巨集的執行速度會比函式快,因為不需要引數壓棧/出棧操作。

5、引數巨集在定義時要多加小心,多加括號。

6、函式只在目標檔案中存在一處,比較節省程式空間。

7、函式的呼叫會牽扯到引數的傳遞,壓棧/出棧操作,速度相對較慢。

8、函式的引數存在傳值和傳位址(指標)的問題,引數巨集不存在

預處理程式提供了條件編譯的功能。條件編譯允許只編譯原始檔中滿足條件的程式 段,使生成的目標程式較短,從而減少了記憶體的開銷,並提高程式的效率,可以按不同的 條件去編譯不同的程式部分,因而產生不同的目標**檔案。這對於程式的移植和除錯是很有用的。

第一種形式:

#ifdef 識別符號

程式段1

#else

程式段2

#endif

第二種形式:

#ifndef 識別符號

程式段1

#else

程式段2

#endif

第三種形式:

#if 常量表示式

程式段1

#else

程式段2

#endif

1.防止乙個標頭檔案被重複包含

#ifndef bodydef_h

#define bodydef_h

//標頭檔案內容

#endif

2、求最大值和最小值

#define  max(x,y) (((x)>(y))?(x):(y))

#define min(x,y) (((x)<(y))?(x):(y))

3、防止溢位的乙個方法

#define  inc_sat(val)  (val = ((val)+1 > (val)) ? (val)+1 : (val))
1、都由多個元素組成

2、各個元素在記憶體中的儲存空間是連續的

3、陣列中各個元素的資料型別相同,而結構體中的各個元素的資料型別可以不相同

定義乙個結構的一般形式為:

struct 結構名

成員表由若干個成員組成,每個成員都是該結構的乙個組成部分。

對每個成員也必須作型別說明。

例如:

struct stu

結構體定義並不是定義乙個變數,而是定義了一種資料型別,這種型別是你定義的,它可以和語言本身所自有的簡單資料型別一樣使用(如 int )。

結構體本身並不會被作為資料而開闢記憶體,真正作為資料而在記憶體中儲存的是這種結構體所定義的變數。

乙個結構體變數占多大記憶體空間呢?這是由這種結構體型別的定義決定的,可以想象為了同時儲存結構體的每乙個成員,那麼結構體變數的儲存大小,就應該是所有分量的儲存空間的總合。

說明結構變數有以下三種方法。以上面定義的stu為例來加以說明。

(1).資料成員的對齊規則:結構體(struct)(或者聯合體(union))的資料成員,第乙個資料成員放在偏移量為0的地方,以後每個資料成員按照#pragma pack(n)和資料成員中比較小的那個數對齊,也就是說,起始位址需要時這個數的倍數,具體下面會舉例說明;

(2).結構體(struct)(或者聯合體(union))整體對齊規則:整體的大小應該按照#pragma pack(n)和結構中最長的資料結構中,最大的那個進行,也就是,需要時間這個數的倍數;

(3).如果#pragma pack(n)比結構中任何乙個資料成員型別都大,則對齊係數不起任何作用。下面舉例說明,環境:vs2013,32位作業系統

1、執行時間不同

關鍵字typedef在編譯階段有效,由於是在編譯階段,因此typedef有型別檢查的功能。

#define則是巨集定義,發生在預處理階段,也就是編譯之前,它只進行簡單而機械的字串替換,而不進行任何檢查。

2、功能有差異

typedef用來定義型別的別名,定義與平台無關的資料型別,與struct的結合使用等。

#define不只是可以為型別取別名,還可以定義常量、變數、編譯開關等。

3、作用域不同

#define沒有作用域的限制,只要是之前預定義過的巨集,在以後的程式中都可以使用。

而typedef有自己的作用域。

(1)乙個位段必須儲存在同一儲存單元(即字)之中,不能跨兩個單元。如果其單元空間不夠,則剩餘空間不用,從下乙個單元起存放該位段。

(2)可以通過定義長度為0的位段的方式使下一位段從下一儲存單元開始。

(3)可以定義無名位段。

(4)位段的長度不能大於儲存單元的長度。

(5)位段無位址,不能對位段進行取位址運算。

(6)位段可以以%d,%o,%x格式輸出。

(7)位段若出現在表示式中,將被系統自動轉換成整數。

預處理,結構體

q 巨集定義的定義和型別。a 巨集定義是由源程式中的巨集定義命令完成的,巨集代換是由預處理程式自動完成的,在 c語言中,巨集定義分為有參和無參兩種。無參巨集巨集名後不帶引數,其定義的一般形式為 define 識別符號 字串 帶參巨集的引數為形參,其一般形式為 define 巨集名 形參表 字串。q ...

記憶體管理 預處理與結構體

1.未初始化的全域性變數 bss段 用來存放那些沒有初始化和初始化為零的全域性變數。2.初始化過的全域性變數 data 裡面存放那些初始化為非零的全域性變數。3.常量資料 rodata段 ro代表ready only,rodata就是用來存放常量資料的。在多個程序是共享的,這樣可以提高執行空間利用率...

記憶體管理與預處理,結構體問題

1 bss段 直觀來說即存放沒有初始化或者初始化為0的全域性變數,一定是全域性變數。2 data 通俗來說 data段 和 bss 沒有太大的區別,只是前者是存放未初始化或者初始化為0的全域性變數,而後者是用來存放那些初始化不為0的全域性變數。注意 兩個都只是存放的全域性變數 3 段 直觀理解為函式...