結構體內成員對齊規則:
1、我們的結構體變數本身就是在4位元組對齊的位置,編譯器幫我們做的事。
2、第乙個成員,就從結構體開始的位址處,存放。這個元素,具體佔多少位元組,由緊挨著下個元素決定。
3、整個成員變數自身都對齊 了,還沒有結束。
4、整個結構體還要是預設位元組對齊的最小整數倍。
結構體預設的位元組對齊:成員變數最大的那個型別所佔位元組
#include
typedef
struct data
d;int main(void)
結果為8byte
注意:
struct
data
s;
int main(void)
結果如下:sizeof(*p1
<< i)=4
0x00x12
#include
struct data
s;int main(void)
結果為16byte
#include
struct data1
;//24
typedef
struct data
s;int main(void)
結果為40
位欄位:專用於結構體,結構體成員的型別必須是:int || unsigned int
有時侯,結構體成員表示的資料很小,就用幾個位來表示。
0欄位,不可訪問,只是佔位整個字中剩下的位,全部寫0
無名字段,不可訪問,只是佔位
字(word)=32bit
下乙個字段不夠在剩餘的字存放時,必須另起乙個字。字段不能跨字。
超出字段表示的資料範圍,結果不可預期
若最後乙個字沒有填滿則也將填滿後返回
欄位不可取位址
#include
struct data1
s1;int main(void)
結果為8byte,同時也是2word
特別的是:
struct
;
#pragma pack(n) (1、2、4、8、.....)
#pragma pack()
這兩個配合使用,表示乙個區間,只有這個區間內的結構體享受這個待遇。
設定 對齊。
如果將n設定為1,就是不對齊
1、充分利用記憶體空間,犧牲了速度,降低了訪問效率。
2、提高效率、效能,犧牲了記憶體空間。
總結:你指定的對齊方式和結構體自身預設對齊方式,倆者取最小的。
#include
#include
#pragma pack(2)
struct data // 16
s;struct data1
s1;#pragma pack()
一旦發生了,系統錯誤就會產生乙個錯誤數字(errno),對應相應的錯誤字串。
c標準定義了兩個值 exit_success 和 exit_failure,可以作為exit()的引數,來分別指示是否為成功退出。
exit(引數)傳遞給的是父程序,或者shell終端
#define
handle_error(msg) dowhile(0)
linux核心裡的兩個巨集:在驅動應用中很廣泛。
off_set_of(type, member)計算結構體內元素的偏移量
containe_of(ptr, type, member),ptr是結構體裡成員的指標,通過呼叫這個巨集計算出結構體的首位址.包含兩句**(表示式),必須要加{}.
這兩個巨集:核心雙鏈表。
分析:
#define off_set_of(type, member) ((long)&(((type *)0)->member))
1、(type *)0指向結構體零位址
2、((type *)0)->member得到了結構體某個成元變數名
3、給這成員變數名,取位址(相對於零位址),此時&(((type *)0)->member)表示是指標型別
4、強制型別轉換成(long)
#define
container_of
(ptr, type, member)
()1、得到結構體成員變數的型別
2、指標賦值(得到真實成員變數的位址值)
4、最後強制型別轉換為結構體指標型別
舉個栗子:
#include
#define off_set_of(type, member) ((long)&(((type *)0)->member))
#define container_of(ptr, type, member) ()
struct da
; // 16
struct data
s = ;
//1、不會因為有結構體成員,而影響你的基本型別,決定預設對齊
//2、裡面的結構體對齊方式,已經在外面決定了(遍歷整個完整結構體)
int main(void)
p->a == (struct data *)0->a;
/*//讓你明白強制轉換0位址
struct data *p;
unsigned long a = 0;
p = (struct data *)a;
p->a == (struct data *)0->a;
*/
typeof(),()裡面的引數可以是變數名或者表示式。
typeof(int) p
int *p, a;
typeof(p) p_a = &a;//將p_a的型別轉換為p的型別,即指標型別
C語言基礎八
define是一條預處理指令,可以用來編寫巨集定義語句。巨集定義語句可以用來給數字起名字。可以在編譯時使用 d選項給乙個名字指定對應的數字,例如 gcc dsize 6 02circle.巨集是可以帶引數的,巨集的引數通常表示乙個名稱 巨集的引數直接參與計算,函式的引數要先製作出乙個替身然後才參與計...
c 基礎 筆記(八)
1 函式模板 1.1 模板分類 函式模板 類模板 1.2 template typename t 告訴編譯器緊跟著下面的函式或類出現 t不要報錯 1.3 void myswap t a t b 1.4 呼叫時候 兩種方式 1.4.1 自動型別推導,比如推導出t型別才能使用模板,不要出現二義性問題 1...
C語言 八 陣列
一維陣列定義與使用 int array 10 定義乙個一維陣列,名字叫array,一共有10個元素,每個元素都是int型別的 array 0 20 array 1 30 array 9 80 陣列索引是從0開始的。陣列在記憶體的儲存方式 陣列在記憶體中就是一段連續的空間,每乙個元素的型別是一樣的。一...