日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解 GNU C 标准中的 typeof 关键字

發布時間:2025/3/12 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解 GNU C 标准中的 typeof 关键字 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果你是 C++ 程序員,應該接觸過 C++11 里的 decltype 操作符,它的作用是自動推導表達式的數據類型,以解決泛型編程中有些類型由模板參數決定而難以(甚至不可能)表示的問題。其實這個特性在 C 語言中也早有類似的實現,GNU C 標準中的一個擴展特性 typeof (PS: 不是 typedef)作用與 decltype 類似,我們來看看這個關鍵字該怎么用。

先來看一個最簡單的例子:

// demo 01
int var = 666;
typeof(int *) pvar = &var;
printf("pvar:\t%p\n", pvar);
printf("&var:\t%p\n", &var);
printf("var:\t%d\n", var);
printf("*pvar:\t%d\n", *pvar);

我們先定義了一個 int 型變量 var,然后再定義一個指針型變量指向 var,一般我們就直接 int *xxx = &xx,但是我們為了演示 typeof 的用法,就不要這么直接了,typeof 是自動推導后面 ( ) 里的數據類型,所以 typeof(int *) 直接推導出了 int * 型,用這個類型聲明了 pvar 并將其初始化為 var 的地址,輸出結果應該就顯而易見了,這是在我的機器上的輸出:

好吧我承認上面那個例子是吃力不討好,明明寫個 int * 簡單又明了,非得加個 typeof 搞得這么晦澀,其實 typeof 的功效在于其能夠自動推導表達式類型,比如我們把剛才的?typeof(int *) 改成 typeof(&var),它也會自動推導出 &var 的類型 —— int * 型,你可以自己試一下,原理是一樣的,這樣的話,當遇到一個非常復雜的表達式我們很難推斷其類型的時候,typeof 就很有用了。另外有一點要注意:typeof 是 GNU C 標準里特有的擴展,標準的 ISO C 并沒有這個關鍵字,所以在編譯的時候不能加任何 ISO 的 C 標準選項,否則會報錯,比如編譯上面的代碼我加入了一個 -std=c90 的選項,編譯器就會有提示一堆 error:

解決的方法很簡單,把 -std=c90 改成 -std=gnu90 即 GNU 的標準即可。

再來幾個例子,比如


// demo 02
int *pvar = NULL;
typeof(*pvar) var = 999;
printf("var:\t%d\n", var);

這個例子是先定義了一個整型指針變量 pvar,typeof 后面括號里的表達式為*pvar,pvar 的類型為 int * 型,那 *pvar 當然就被解析為 int 型,所以用這個類型聲明的變量 var 也是 int 型,就相當于 int var = 999; 輸出結果如下:


再來:


// demo 03
int *pvar = NULL;
typeof(*pvar) var[4] = {11, 22, 33, 44};
for (int i = 0; i < 4; i++)
?? ?printf("var[%d]:\t%d\n", i, var[i]);
這次 typeof 解析出來的類型跟上一個一樣,區別是 var 是一個包含四個元素的數組,相當于 int var[4] = {...}; 輸出如下:


這次來個有點水平的:


// demo 04
typeof(typeof(const char *)[4]) pchar = {"hello", "world", "good", "night"};
for (int i = 0; i < 4; i++)
?? ?printf("pchar[%d]:\t%s\n", i, pchar[i]);

這次看起來就比較復雜了,考驗你指針功底的時候到了,他嵌套了兩層 typeof,我們一層一層的往外剝,先看最里層,typeof 先解析出一個 const char * 類型,有經驗的 C 程序員應該馬上就能聯想到字符串了吧,而后面又跟著一個 [4],說明這是一個包含四個字符串的數組類型,那么這個類型也就被最外層的 typeof 給解析到了,那么最終的 pchar 也就是這個類型了,相當于 const char *pchar[4] = {...};?


再來考驗一下你的指針,這次是函數指針:


// demo 05
int add(int param1, int param2) {
?? ?return param1 + param2;
}
?
int sub(int param1, int param2) {
?? ?return param1 - param2;
}
?
int mul(int param1, int param2) {
?? ?return param1 * param2;
}
?
int main() {
?? ?int (*func[3]) (int, int) = {add, sub, mul};
?? ?typeof(func[0](1, 1)) sum = 100;
?? ?typeof(func[1](1, 1)) dif = 101;
?? ?typeof(func[2](1, 1)) pro = 102;
?
?? ?printf("sum:\t%d\n", sum);
?? ?printf("dif:\t%d\n", dif);
?? ?printf("pro:\t%d\n", pro);
?? ?return 0;
}

這個 demo 中先定義了三個函數,這三個函數都是返回值為 int 類型,并且接受兩個 int 型的參數,然后在 main 函數中定義了一個函數指針數組 func,并用上面三個函數名將其初始化,然后我們來看底下的第一個 typeof ?會推導出什么類型,func[0] 就是指 add 這個函數,后面的括號里跟了兩個參數,說白了就是簡單的 add(1, 1) 的調用,而 add 會返回一個 int 型值,所以最終推導出的類型就是 int 型,其它兩個都是同理,所以 sum、dif、pro 其實就是三個整型數,相當于 int sum = 100; int dif = 101; int pro = 102; 好吧,我承認這個 demo 有點坑,而且這個例子舉得不恰當,輸出結果就是它們分別的值:


我們再看看它在宏定義中的應用:


// demo 06
#define pointer(T) ?typeof(T *)
#define array(T, N) typeof(T[N])
?
int main() {
?? ?array(pointer(char), 4) pchar = {"hello", "world", "good", "night"};
?? ?for (int i = 0; i < 4; i++)
?? ??? ?printf("pchar[%d]:\t%s\n", i, pchar[i]);
?? ?return 0;
}

這里用到了宏函數,pointer(T) 會被替換為 typeof(T *),也就是說 pointer 后面跟某個類型的名字,經過預處理之后就會變成用 typeof 解析相應類型的指針類型,而 array 后面跟一個類型名和一個整數,然后 typeof 就會解析為該類型的一個數組,這樣 main 函數中的?array(pointer(char), 4),pointer(char) 首先會被解析為 char * 型,然后外層的 array 會再被解析為包含 4 個 char * 元素的數組類型,所以就相當于 char *pchar[4] = {...}; 輸出結果如下:


好了,啰嗦了這么多,typeof 這個關鍵字總算是知道用來干什么了吧,感覺好像語法挺晦澀的,而且沒有什么實際用途,那好吧,我再讓大伙看一看實際項目中的一個例子:


/*
?* 選自 linux-2.6.7 內核源碼
?* filename: linux-2.6.7/include/linux/kernel.h
?*/
#define min(x,y) ({ \
?? ?typeof(x) _x = (x);?? ?\
?? ?typeof(y) _y = (y);?? ?\
?? ?(void) (&_x == &_y);?? ??? ?\
?? ?_x < _y ? _x : _y; })
上面這個例子是選自 linux 2.6.7 內核中?include/linux/kernel.h 這個頭文件,宏定義 min 的作用是從兩個相同類型的對象中選取一個最小的,它接受兩個參數 x 和 y,后面的宏替換部分就用 typeof 定義兩個變量 _x 和 _y,并分別賦值為 x y,這里用 typeof 的作用就是可以讓 min 接受任何類型的參數而不必局限于某一個單一類型,這有點泛型編程的味道了,最后一個語句?_x < _y ? _x : _y; 用了一個條件運算符來返回二者之中最小的,中間還有一句?(void) (&_x == &_y); 看起來好像是廢話,其實這句話是有特殊用意的,因為我們不能保證你在使用 min 的時候傳入的兩個參數都是相同的類型,這時候就需要做一個檢測,而 C 語言不支持直接 typeof(_x) == typeof(_y) 這樣的操作,所以就取其地址,用指針類型來比較,如果兩個指針的類型不一致,編譯器就會產生警告以達到檢測的效果,至于前面的 (void),是因為僅表達式 &_x == &_y 本身是沒有意義的,如果沒有這個 (void) 編譯器同樣會警告:statement with no effect [-Wunused-value],無效的語句,如果不想看到這個警告,那就在前面加個?(void) 忽略掉。


參考資料:

GNU 官方手冊:https://gcc.gnu.org/onlinedocs/gcc/Typeof.html


crifan 的個人網站:http://www.crifan.com/order_min__macro_definition_void_amp__x__amp__y_the_meaning_of/

-

總結

以上是生活随笔為你收集整理的详解 GNU C 标准中的 typeof 关键字的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 摸摸摸bbb毛毛毛片 午夜爽爽影院 | 69人妻精品久久无人专区 | 国产精品第12页 | 性感美女高潮 | 亚洲av少妇一区二区在线观看 | 天天插天天色 | 亚洲精品无码久久久久久久 | juliaannxxxxx高清| 视频国产精品 | 国产午夜网站 | 久一视频在线 | 巨大乳の揉んで乳榨り奶水 | 亚洲视频六区 | xxx视频网站 | 国产一区二区免费视频 | 国产精品观看 | 亚洲人丰满奶水 | 精品国产视频一区二区 | 亚洲在线网站 | 波多野结衣av在线观看 | 五十路在线观看 | 骚虎视频最新网址 | 亚洲av综合永久无码精品天堂 | 国产精品久久久免费视频 | 国产精品精品 | 久久久www免费人成人片 | 999国产精品视频 | 性色av一区二区三区在线观看 | 91色综合 | 天天干天天谢 | 精品国产乱码久久久久久免费 | 日本a√在线观看 | 亚洲麻豆av | 久久视频中文字幕 | 亚洲AV无码成人精品区明星换面 | 精一区二区 | 欧美午夜性春猛交 | 日本体内she精高潮 男女视频在线免费观看 | 无遮挡在线观看 | 色天堂影院 | 久久综合久久网 | 丁香花在线影院观看在线播放 | 乳女教师の诱惑julia | 少妇按摩一区二区三区 | 久久精品人人做人人爽 | 国产美女91| 看av免费毛片手机播放 | jizz毛片| 乱xxxxx普通话对白 | 亚洲国产aⅴ精品一区二区 日韩黄色在线视频 | 在线播放少妇奶水过盛 | 日日天天干| 性欧美久久 | 久久久久中文字幕 | 亚洲久草视频 | 自拍偷拍在线播放 | 少妇太紧太爽又黄又硬又爽 | 一级爱爱片 | 成人免费av片 | av在线免费不卡 | 国产1页 | 91视频你懂的 | 亚洲免费观看视频 | 特种兵之深入敌后高清全集免费观看 | 免费毛片一级 | 久久亚洲天堂网 | 亚洲春色另类 | 亚洲精品电影院 | 欧美日韩成人精品 | 欧美中文字幕在线 | 91爱爱爱爱 | 亚洲精品无码久久久 | 人人草人人 | 天堂资源在线 | 国产日韩欧美日韩大片 | 欧美激情va永久在线播放 | 少妇h视频| 亚洲自拍电影 | 亚洲精品乱码久久久久久麻豆不卡 | 国产乱码精品一区二区三区五月婷 | 日韩欧美中文在线 | 美女黄视频在线观看 | 中文字幕在线视频一区二区 | 蜜桃在线一区二区三区 | 黄色片免费 | 91精产国品| 成人免费视频软件网站 | 国产私密视频 | 色哟哟视频 | av大帝| 麻豆一区二区99久久久久 | 国产对白videos麻豆高潮 | 日b视频免费看 | 我们的生活第五季在线观看免费 | 国产日本视频 | 欧美日韩视频免费观看 | 91免费成人 | 男女考妣视频 | 婷婷一级片 |