真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C語(yǔ)言僅憑自學(xué)能到什么高度?-創(chuàng)新互聯(lián)

先來(lái)測(cè)測(cè)你現(xiàn)在的C語(yǔ)言水平怎么樣...

創(chuàng)新互聯(lián)基于分布式IDC數(shù)據(jù)中心構(gòu)建的平臺(tái)為眾多戶提供達(dá)州托管服務(wù)器 四川大帶寬租用 成都機(jī)柜租用 成都服務(wù)器租用。

假如現(xiàn)在你去一家公司面試,要求:定義一個(gè)宏,求兩個(gè)數(shù)中的大數(shù)。

此處不要再往下看,停頓5分鐘,寫(xiě)出你的答案,然后跟后面的答案對(duì)比。

-----------停頓5分鐘------------------------------------

合格

對(duì)于學(xué)過(guò)C語(yǔ)言的同學(xué),寫(xiě)出這個(gè)宏基本上不是什么難事,使用條件運(yùn)算符就能完成:

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

這是最基本的C語(yǔ)言語(yǔ)法,如果連這個(gè)也寫(xiě)不出來(lái),估計(jì)場(chǎng)面會(huì)比較尷尬。面試官為了緩解尷尬,一般會(huì)對(duì)你說(shuō):小伙子,你很棒,回去等消息吧,有消息,我們會(huì)通知你!這時(shí)候,你應(yīng)該明白:不用再等了,趕緊把這篇文章看完,接著面下家。這個(gè)宏能寫(xiě)出來(lái),也不要覺(jué)得你很牛X,因?yàn)檫@只能說(shuō)明你有了C語(yǔ)言的基礎(chǔ),但還有很大的進(jìn)步空間。比如,我們寫(xiě)一個(gè)程序,驗(yàn)證一下我們定義的宏是否正確:

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

測(cè)試程序么,我們肯定要把各種可能出現(xiàn)的情況都測(cè)一遍。這不,測(cè)試第4行語(yǔ)句,當(dāng)宏的參數(shù)是一個(gè)表達(dá)式,發(fā)現(xiàn)實(shí)際運(yùn)行結(jié)果為max=0,跟我們預(yù)期結(jié)果max=1不一樣。這是因?yàn)椋暾归_(kāi)后,就變成了這個(gè)樣子:

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

因?yàn)楸容^運(yùn)算符 >的優(yōu)先級(jí)為6,大于 !=(優(yōu)先級(jí)為7),所以展開(kāi)的表達(dá)式,運(yùn)算順序發(fā)生了改變,結(jié)果就跟我們的預(yù)期不一樣了。為了避免這種展開(kāi)錯(cuò)誤,我們可以給宏的參數(shù)加一個(gè)小括號(hào)()來(lái)防止展開(kāi)后,表達(dá)式的運(yùn)算順序發(fā)生變化。這樣的宏才能算一個(gè)合格的宏:

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

上面的宏,只能算合格,但還是存在漏洞。比如,我們使用下面的代碼測(cè)試:

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

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

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

因?yàn)檫\(yùn)算符 + 的優(yōu)先級(jí)大于比較運(yùn)算符 >,所以這個(gè)表達(dá)式就變?yōu)?>2?1:2,最后結(jié)果為1也就見(jiàn)怪不怪了。此時(shí)我們應(yīng)該繼續(xù)修改這個(gè)宏:

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

使用小括號(hào)將宏定義包起來(lái),這樣就避免了當(dāng)一個(gè)表達(dá)式同時(shí)含有宏定義和其它高優(yōu)先級(jí)運(yùn)算符時(shí),破壞整個(gè)表達(dá)式的運(yùn)算順序。如果你能寫(xiě)到這一步,說(shuō)明你比前面那個(gè)面試合格的同學(xué)強(qiáng),前面那個(gè)同學(xué)已經(jīng)回去等消息了,我們接著面試下一輪。

良好

上面的宏,雖然解決了運(yùn)算符優(yōu)先級(jí)帶來(lái)的問(wèn)題,但是仍存在一定的漏洞。比如,我們使用下面的測(cè)試程序來(lái)測(cè)試我們定義的宏:

#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;
}

在程序中,我們定義兩個(gè)變量 i 和 j,然后比較兩個(gè)變量的大小,并作自增運(yùn)算。實(shí)際運(yùn)行結(jié)果發(fā)現(xiàn)max = 7,而不是預(yù)期結(jié)果max = 6。這是因?yàn)樽兞?i 和 j 在宏展開(kāi)后,做了兩次自增運(yùn)算,導(dǎo)致打印出 i 的值為7。

遇到這種情況,那該怎么辦呢? 這時(shí)候,語(yǔ)句表達(dá)式就該上場(chǎng)了。我們可以使用語(yǔ)句表達(dá)式來(lái)定義這個(gè)宏,在語(yǔ)句表達(dá)式中定義兩個(gè)臨時(shí)變量,分別來(lái)暫儲(chǔ) i 和 j 的值,然后進(jìn)行比較,這樣就避免了兩次自增、自減問(wèn)題。

#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;
}

在語(yǔ)句表達(dá)式中,我們定義了2個(gè)局部變量_x、_y來(lái)存儲(chǔ)宏參數(shù) x 和 y 的值,然后使用 _x 和 _y 來(lái)比較大小,這樣就避免了 i 和 j 帶來(lái)的2次自增運(yùn)算問(wèn)題。

你能堅(jiān)持到了這一關(guān),并寫(xiě)出這樣自帶BGM的宏,面試官心里可能已經(jīng)有了給你offer的意愿了。但此時(shí)此刻,千萬(wàn)不要驕傲!為了徹底打消面試官的心理顧慮,我們需要對(duì)這個(gè)宏繼續(xù)優(yōu)化。

優(yōu)秀

在上面這個(gè)宏中,我們定義的兩個(gè)臨時(shí)變量數(shù)據(jù)類型是int型,只能比較兩個(gè)整型的數(shù)據(jù)。那對(duì)于其它類型的數(shù)據(jù),就需要重新再定義一個(gè)宏了,這樣太麻煩了!我們可以基于上面的宏繼續(xù)修改,讓它可以支持任意類型的數(shù)據(jù)比較大?。?/p>

#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;
}

在這個(gè)宏中,我們添加一個(gè)參數(shù):type,用來(lái)指定臨時(shí)變量 _x 和 _y 的類型。這樣,我們?cè)诒容^兩個(gè)數(shù)的大小時(shí),只要將2個(gè)數(shù)據(jù)的類型作為參數(shù)傳給宏,就可以比較任意類型的數(shù)據(jù)了。如果你能在面試中,寫(xiě)出這樣的宏,面試官肯定會(huì)非常高興,他一般會(huì)跟你說(shuō):小伙子,稍等,待會(huì)HR會(huì)跟你談待遇問(wèn)題。

還能不能更牛逼?

如果你想薪水拿得高一點(diǎn),待遇好一點(diǎn),此時(shí)不應(yīng)該驕傲,你應(yīng)該大手一揮:且慢,我還可以更牛逼!

上面的宏定義中,我們?cè)黾恿艘粋€(gè)type類型參數(shù),來(lái)兼容不同的數(shù)據(jù)類型,此時(shí)此刻,為了薪水,我們應(yīng)該把這個(gè)也省去。如何做到?使用typeof就可以了,typeof是GNU C新增的一個(gè)關(guān)鍵字,用來(lái)獲取數(shù)據(jù)類型,我們不用傳參進(jìn)去,讓typeof直接獲取!

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

在這個(gè)宏定義中,使用了typeof關(guān)鍵字用來(lái)獲取宏的兩個(gè)參數(shù)類型。干貨在(void) (&x == &y);這句話,簡(jiǎn)直是天才般的設(shè)計(jì)!一是用來(lái)給用戶提示一個(gè)警告,對(duì)于不同類型的指針比較,編譯器會(huì)給一個(gè)警告,提示兩種數(shù)據(jù)類型不同;二是,當(dāng)兩個(gè)值比較,比較的結(jié)果沒(méi)有用到,有些編譯器可能會(huì)給出一個(gè)warning,加個(gè)(void)后,就可以消除這個(gè)警告!

此刻,面試官看到你的這個(gè)宏,估計(jì)會(huì)倒吸一口氣:乖乖,果然是后生可畏,這家伙比我還牛逼!你等著,HR待會(huì)過(guò)來(lái)跟你談薪水!恭喜你,拿到offer了!

打造一個(gè)趨近完美的宏

以上的宏解決了自增自減運(yùn)算符 ++/-- 帶來(lái)的一系列問(wèn)題。但也不是十全十美,通過(guò)激情討論,發(fā)現(xiàn)還是有漏洞:在宏內(nèi)部的語(yǔ)句表達(dá)中,我們定義了2個(gè)臨時(shí)變量 _x 和 _y解決了 ++/-- 帶來(lái)的問(wèn)題,但是也引入了一個(gè)新漏洞,比如使用下面的代碼時(shí):

max(x, _x)

當(dāng)宏展開(kāi)后,第二個(gè)參數(shù)就與宏內(nèi)部定義的臨時(shí)變量同名了,這就影響宏最后的結(jié)果。因此,為了防止用戶傳入的參數(shù)跟宏內(nèi)部的臨時(shí)變量產(chǎn)生同名沖突,我們可以將宏內(nèi)部的臨時(shí)變量盡量定義得復(fù)雜一些,降低同名的概率,比如Linux 內(nèi)核中max宏的定義:

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

在上面的宏定義中,雖然臨時(shí)變量 _max1 和max2 比我們上面的_x 和 _y 好點(diǎn),也只是更進(jìn)一步降低跟用戶的傳參同名沖突的概率,但是還是不能完全杜絕。極端一點(diǎn),我們可以把這兩個(gè)變量定義得無(wú)比長(zhǎng)、無(wú)比奇葩,只要不超過(guò)C標(biāo)準(zhǔn)規(guī)定以的標(biāo)識(shí)符大長(zhǎng)度j就可以:

_____________tmp______________________for_______________________max______

再奇葩的程序員,再豬一樣的隊(duì)友,哪怕是團(tuán)隊(duì)毒瘤、代碼殺手,估計(jì)也不會(huì)定義這樣的變量吧!這樣同名沖突的概率就大大降低了,但是還是不能完全杜絕,算是Linux內(nèi)核的一個(gè)小漏洞吧。

還好下載新版本的Linux內(nèi)核,發(fā)現(xiàn)已經(jīng)堵住了這個(gè)漏洞:

#define __max(t1, t2, max1, max2, x, y) ({              \
	t1 max1 = (x);                                  \
	t2 max2 = (y);                                  \
	(void) (&max1 == &max2);                        \
	max1< max2 ? max1 : max2; })

#define ___PASTE(a,b) a##b
#define __PASTE(a,b) ___PASTE(a,b)

#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)

#define max(x, y)                                       \
	__max(typeof(x), typeof(y),                     \
	      __UNIQUE_ID(max1_), __UNIQUE_ID(max2_),   \
	      x, y)

在新版的宏中,內(nèi)部的臨時(shí)變量不再由程序員自己定義,而是讓編譯器生成一個(gè)獨(dú)一無(wú)二的變量,這樣就避免了同名沖突的風(fēng)險(xiǎn)。宏__UNIQUE_ID的作用就是生成了一個(gè)獨(dú)一無(wú)二的變量,確保了臨時(shí)變量的唯一性。

小結(jié):

上面以一個(gè)宏為例子,意在說(shuō)明,對(duì)一門語(yǔ)言的掌握是永無(wú)止境的,就算你把當(dāng)前所有的C語(yǔ)言知識(shí)點(diǎn)、編程技能都掌握了,C語(yǔ)言也是不斷更新的、C標(biāo)準(zhǔn)也是不斷更新變化的。編程技巧、編程技能也是不斷進(jìn)步的。

而自學(xué)往往是最有效的學(xué)習(xí)方法,但是前提是你要有好的學(xué)習(xí)資料、學(xué)習(xí)方法、學(xué)習(xí)目標(biāo),再加上刻意練習(xí)和實(shí)時(shí)反饋。否則,就是兩眼一抹黑,不知道自己學(xué)得怎么樣、學(xué)到什么水平了、學(xué)了有什么用、學(xué)得對(duì)不對(duì)。其實(shí)還有一種比較有效的學(xué)習(xí)方法,找個(gè)行業(yè)內(nèi)的工程師帶一帶、參考優(yōu)秀的書(shū)籍、教程學(xué)一學(xué)、再結(jié)合幾個(gè)項(xiàng)目練一練,就知道什么該學(xué)、要學(xué)到什么程度,而且可以大大提高學(xué)習(xí)效率。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


本文名稱:C語(yǔ)言僅憑自學(xué)能到什么高度?-創(chuàng)新互聯(lián)
本文鏈接:http://weahome.cn/article/geose.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部