typeof關鍵字在核心中的運用

2021-10-04 05:10:20 字數 2732 閱讀 2133

ansi c定義了sizeof關鍵字,用來獲取乙個變數和資料型別在記憶體中所佔的儲存位元組數。gnu 擴充套件了乙個關鍵字,typeof用來獲取乙個變數或表示式的型別。

int i;

typeof(i) j = 20;

typeof(int *) a;

int f();

typeof(f()) k;

在上面的**中,因為變數i的型別為int,所以typeof(i)就等於int,typeof(i) j = 20就相當於int j = 20;typeof(int *) a;就相當於int * a;函式也是有型別的,函式的型別就是其返回值型別,所以typeof(f()) k;就相當於int k;。

typeof( typeof(int *)[5] ) a; //相當於int * a[5];

typeof( int x[5]) y; //相當於int y[5];

青銅級別:

#define max(x,y) ( (x) > (y)?(x):(y) )
**級別:

#definemax(type,x,y)()
該方法通過新增乙個type引數解決了不同型別變數比較的問題;通過定義臨時變數_x和_y成功解決了引數的***問題。但他還不是最好的。

**級別:

#define max(x,y) ()
通過typeof直接獲取巨集的引數型別,這樣我們就不必再單獨將引數的型別傳給巨集了。到這裡他已經基本可以在江湖中有自己一席之地了,但離號令天下還有一步之遙。

磚石級別:

#definemax(x,y)()
該巨集定義之所以稱之為鑽石級別,是因為他多了一句(void)(&_x==&_y); 該語句看起來貌似一句廢話,但其實用的很巧妙。它主要是用來檢測巨集的兩個引數的資料型別是否相同。如果不相同,編譯器會給乙個警告資訊提醒開發人員。

waring:comparison of distinct pointer types lacks a cast
從字面意思來看,他用來判斷兩個變數的位址是否相等。可能有人會說,兩個變數的位址怎麼可能相等呢?但妙就妙在這個地方!當該語句還未執行到判斷兩個變數的位址是否相等的時候,編譯器首先要檢查兩個變數的資料型別是否相同。如果兩個變數的資料型別不相同的話,那麼編譯器會有警告資訊。當然我們也就可以從中獲益。而如果兩個變數的資料型別相等的話,那麼該語句在整個巨集中也不起任何作用,同樣我們也沒任何損失,笑問這種無本生意為何不做呢?

所謂是驢子是馬拉出來溜溜!上面我們講了這麼多,但sizeof關鍵字到底有什麼作用呢?下面通過解剖核心巨集container_of來為大家展示sizeof關鍵字的強大作用和核心設計者的巨大腦洞。

首先讓我們來膜拜一下天下第一巨集的風采:

#define offsetof( type, member ) ( (size_t)&((type *)0)->member )

#define container_of(ptr, type,member) ()

也就是說,只要我們知道了乙個結構體的型別,結構體內某一成員的位址,就可以直接獲得這個結構體的首位址。這個巨集返回的就是這個結構體的首位址。

作為一名linux核心驅動開發者,除了要面對各種手冊、底層暫存器,有時候還要應付底層造輪子的事情。為了系統的穩定和效能,有時候我們不得不深入底層,死磕某個模組進行分析和優化。底層的工作雖然很有挑戰性,但有時候也是很枯燥的。不像應用開發那樣有意思,所以為了提高對工作的興趣,大家表面上雖然不說自己牛叉,但內心深處一定要建立起自己的職位優越感。人不可有傲氣,但不能無傲骨。我們可不像開發,知道api介面、讀讀文件、完成功能就ok了。作為一名底層開發者要時刻記住:要和暫存器、記憶體、硬體電路等各種底層群眾打成一片。從群眾中來,到群眾中去,急群眾之所急,想群眾之所想。這樣才能構建乙個穩定和諧的嵌入式社會。

#defineoffsetof(type,member)((size_t)&((type*)0)->member)
這個巨集有兩個引數,乙個是結構體型別type,乙個是結構體的成員member。它使用的技巧就是:將0強制轉換為乙個指向type型別的結構體常量指標。因為常量指標為0,即可以看做結構體首位址為0,所以結構體每個成員變數的位址即為該成員相對於結構體首位址的偏移。最後通過強制型別轉換size_t,將成員位址值轉換為整數,取得其在整個結構體中的偏移。

consttypeof(((type*)0)->member)_mptr=(ptr);
因為結構體的成員資料型別可以是任意的資料型別,所以為了讓這個巨集相容各種資料型別,我們定義了乙個臨時指標變數_mptr,該變數用來儲存結構體成員member的位址ptr。那如何獲取ptr指標型別的呢?就是通過上面的巨集語句。

(type*)((char*)_mptr-offsetof(type,member));
最後通過該成員變數位址_mptr減去該成員在結構體中的偏移,就得到了結構體的首位址。當然因為返回的是結構體的首位址所以資料型別還必須強制轉換一下。

好了到這裡我們對天下第一巨集的分析也就接近尾聲了。那麼可以看出任何乙個複雜的東西,我們都可以把它分解。運用所學的基礎知識一層一層,一點以一點去剖析,先去降維分析,然後再進行綜合。那麼這種能力就是你的核心競爭力,也是你超越其他工程師脫穎而出的機會!

typeof關鍵字簡介

typeof關鍵字是c語言中的乙個新擴充套件。只要可以接受typedef名稱,sun studio c 編譯器就可以接受帶有typeof的結構,包括以下語法類別 宣告函式宣告符中的引數型別鍊錶和返回型別 型別定義 型別操作符s sizeof操作符 復合文字 typeof實參 編譯器接受帶雙下劃線的關...

typeof關鍵字的作用

前言 typeof關鍵字是c語言中的乙個新擴充套件,這個特性在linux核心中應用非常廣泛。其實這和c 的auto關鍵字和可以推斷decltype關鍵字相當類似 1,把y定義成x指向的資料型別 typeof x y 2,把y定義成x指向資料型別的陣列 typeof x y 4 3,把y定義成乙個字元...

typeof關鍵字簡介 rtti

typeof 關鍵字是c語言中的乙個新擴充套件。只要可以接受typedef 名稱,sun studio c 編譯器就可以接受帶有typeof 的結構,包括以下語法類別 編譯器接受帶雙下劃線的關鍵字 typeof 和 typeof 本文中的例子並沒有遵循使用雙下劃線的慣例。從語句構成上看,typeof...