測測你的C語言功底怎么樣

很多時候當你完成了C語言語法的學(xué)習(xí),特別適合一些擴展用法之后熊楼,自身會陷入一個自滿的大坑鸭叙,以為自己啥都會了觉啊,但其實自己水平到底怎樣,你自己也不知道沈贝。那么今天我就帶著大家測一測你的嵌入式C學(xué)的到底有多牛(low)杠人。

自測題:請定義一個宏,求兩個數(shù)中的最大數(shù)宋下。

不合格水平

對于學(xué)過C語言的同學(xué)嗡善,寫出這個宏基本上不是什么難事,使用條件運算符就能完成:

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

這是最基本的C語言語法学歧,如果連這個也寫不出來罩引,估計你還沒進C的大門。但一般這種水平枝笨,公司是不會要你的袁铐,因為你還是門外漢!
不信横浑?舉個反例剔桨,驗證一下我們定義的宏是否正確:

#define   MAX(x,y)    x > y ? x : y
int main(void)
{
    printf("max=%d",MAX(1!=1,1!=2));
    return 0;
}

當宏的參數(shù)是一個表達式,發(fā)現(xiàn)實際運行結(jié)果為max=0,跟我們預(yù)期結(jié)果max=1不一樣伪嫁。這是因為领炫,宏展開后,就變成了這個樣子:

printf("max=%d",1!=1>1!=2?1!=1:1!=2);

因為比較運算符 > 的優(yōu)先級為6张咳,大于 !=(優(yōu)先級為7)帝洪,所以展開的表達式,運算順序發(fā)生了改變脚猾,結(jié)果就跟我們的預(yù)期不一樣了葱峡。

合格水平

為了避免這種展開錯誤,我們可以給宏的參數(shù)加一個小括號()來防止展開后龙助,表達式的運算順序發(fā)生變化砰奕。這樣的宏才能算一個合格的宏:

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

但上面的宏還是存在漏洞。
比如提鸟,我們使用下面的代碼測試:

#define  MAX(x,y)  (x) > (y) ? (x) : (y)
int main(void)
{
    printf("max=%d",3 + MAX(1,2));
    return 0;
}

在程序中军援,我們打印表達式 3 + MAX(1, 2) 的值,預(yù)期結(jié)果應(yīng)該是5称勋,但實際運行結(jié)果卻是1胸哥。我們展開后,發(fā)現(xiàn)同樣有問題:

3 + (1) > (2) ? (1) : (2);

因為運算符 + 的優(yōu)先級大于比較運算符 >赡鲜,所以這個表達式就變?yōu)?>2?1:2空厌,最后結(jié)果為1也就見怪不怪了庐船。

中等水平

我們繼續(xù)修改這個宏:

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

使用小括號將宏定義包起來,這樣就避免了當一個表達式同時含有宏定義和其它高優(yōu)先級運算符時嘲更,破壞整個表達式的運算順序筐钟。
上面的宏,雖然解決了運算符優(yōu)先級帶來的問題赋朦,但是仍存在一定的漏洞篓冲。
比如:

#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void)
{
    int i = 2;
    int j = 6;
    printf("max=%d",MAX(i++,j++));
    return 0;
}

在程序中,我們定義兩個變量 i 和 j北发,然后比較兩個變量的大小纹因,并作自增運算。實際運行結(jié)果發(fā)現(xiàn)max = 7琳拨,而不是預(yù)期結(jié)果max = 6瞭恰。這是因為變量 i 和 j 在宏展開后,做了兩次自增運算狱庇,導(dǎo)致打印出 i 的值為7惊畏。

良好水平

遇到這種情況,語句表達式就該上場了密任。我們可以使用語句表達式來定義這個宏颜启,在語句表達式中定義兩個臨時變量,分別來暫儲 i 和 j 的值浪讳,然后進行比較缰盏,這樣就避免了兩次自增、自減問題淹遵。

#define MAX(x,y)({  \
    int _x = x;   \
    int _y = y;   \
    _x > _y ? _x : _y; \
})
int main(void)
{
    int i = 2;
    int j = 6;
    printf("max=%d",MAX(i++,j++));
    return 0;
}

在語句表達式中口猜,我們定義了2個局部變量_x、_y來存儲宏參數(shù) x 和 y 的值透揣,然后使用 _x 和 _y 來比較大小济炎,這樣就避免了 i 和 j 帶來的2次自增運算問題。
如果你能堅持到了這一關(guān)辐真,并寫出這樣自帶BGM的宏须尚,說明你有了比較好的語言基礎(chǔ),是可雕琢一塊木頭侍咱,面試官心里可能已經(jīng)有了給你offer的意愿了耐床。

優(yōu)秀水平

在上面這個宏中,我們定義的兩個臨時變量數(shù)據(jù)類型是int型楔脯,只能比較兩個整型的數(shù)據(jù)撩轰。那對于其它類型的數(shù)據(jù),就需要重新再定義一個宏了,這樣太麻煩了钧敞!我們可以基于上面的宏繼續(xù)修改,讓它可以支持任意類型的數(shù)據(jù)比較大恤锪浮:

#define MAX(type,x,y)  ( {  \
    type _x = x;     \
    type _y = y;     \
    _x > _y ? _x : _y; \
})

int main(void)
{
    int i = 2;
    int j = 6;
    printf("max=%d\n",MAX(int,i++,j++));
    printf("max=%f\n",MAX(float,3.14,3.15));
    return 0;
}

在這個宏中溉苛,我們添加一個參數(shù):type,用來指定臨時變量 _x 和 _y 的類型弄诲。這樣愚战,我們在比較兩個數(shù)的大小時,只要將2個數(shù)據(jù)的類型作為參數(shù)傳給宏齐遵,就可以比較任意類型的數(shù)據(jù)了寂玲。如果你能寫出這樣的宏,說明你是可雕琢的一塊玉梗摇,試官肯定會非常高興他遇到了你拓哟。

超優(yōu)秀水平

上面的宏定義中,我們增加了一個type類型參數(shù)伶授,來兼容不同的數(shù)據(jù)類型,此時此刻,為了這個超畔咧,我們應(yīng)該把這個也省去某抓。
如何做到?使用typeof就可以了疮蹦,typeof是GNU C新增的一個關(guān)鍵字诸迟,用來獲取數(shù)據(jù)類型,我們不用傳參進去愕乎,讓typeof直接獲日笪!

#define max(x, y) ({    \
    typeof(x) _x = (x); \
    typeof(y) _y = (y); \
    (void) (&_x == &_y);\
     _x > _y ? _x : _y; 
})

在這個宏定義中妆毕,使用了typeof關(guān)鍵字用來獲取宏的兩個參數(shù)類型慎玖。干貨在(void) (&x == &y);這句話,簡直是天才般的設(shè)計笛粘!一是用來給用戶提示一個警告趁怔,對于不同類型的指針比較,編譯器會給一個警告薪前,提示兩種數(shù)據(jù)類型不同润努;二是,當兩個值比較示括,比較的結(jié)果沒有用到時铺浇,有些編譯器可能會給出一個warning,加個(void)后垛膝,就可以消除這個警告

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鳍侣,一起剝皮案震驚了整個濱河市丁稀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倚聚,老刑警劉巖线衫,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異惑折,居然都是意外死亡授账,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門惨驶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來白热,“玉大人,你說我怎么就攤上這事粗卜∥萑罚” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵休建,是天一觀的道長乍恐。 經(jīng)常有香客問我,道長测砂,這世上最難降的妖魔是什么茵烈? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮砌些,結(jié)果婚禮上呜投,老公的妹妹穿的比我還像新娘。我一直安慰自己存璃,他們只是感情好仑荐,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纵东,像睡著了一般粘招。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上偎球,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天洒扎,我揣著相機與錄音,去河邊找鬼衰絮。 笑死袍冷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的猫牡。 我是一名探鬼主播胡诗,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了煌恢?” 一聲冷哼從身側(cè)響起骇陈,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瑰抵,沒想到半個月后缩歪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡谍憔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了主籍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片习贫。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖千元,靈堂內(nèi)的尸體忽然破棺而出苫昌,到底是詐尸還是另有隱情,我是刑警寧澤幸海,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布祟身,位于F島的核電站,受9級特大地震影響物独,放射性物質(zhì)發(fā)生泄漏袜硫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一挡篓、第九天 我趴在偏房一處隱蔽的房頂上張望婉陷。 院中可真熱鬧,春花似錦官研、人聲如沸秽澳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽担神。三九已至,卻和暖如春始花,著一層夾襖步出監(jiān)牢的瞬間妄讯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工衙荐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捞挥,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓忧吟,卻偏偏與公主長得像砌函,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容