引言:經(jīng)常在一些社區(qū)上看到莫名的一句話
PHP是世界上最好的語言
,在語言的爭論上,確實(shí)是大有華山論劍
的門派之爭。本文將通過編程語言的范式
角度番枚,來了解整個(gè)編程語言的發(fā)展史法严,同時(shí)更清晰的認(rèn)知編程范式
,以達(dá)到知己知彼葫笼,百戰(zhàn)不殆
??編程語言發(fā)展到今天深啤,出現(xiàn)了好多不同的代碼編寫方式,但不同的方式解決的都是同一個(gè)問題路星,那就是如何寫出更為通用溯街、更具可重用性的代碼或模塊。
一洋丐、從C語言談起
??C語言的歷史悠久呈昔,自其問世以來,其影響了太多太多的編程語言垫挨,到現(xiàn)在還一直被廣泛使用韩肝,不得不佩服它的生命力。但是九榔,我們也要清楚的知道哀峻,大多數(shù)的使用C語言來做內(nèi)核的編程語言其實(shí)都是在改善C語言帶來的問題+時(shí)代發(fā)展帶來的變化。
下面來簡單回顧下C語言的特性:
- C 語言是一個(gè)靜態(tài)弱類型語言哲泊,在使用變量時(shí)需要聲明變量類型剩蟀,但是類型間可以有隱式轉(zhuǎn)換;
- 不同的變量類型可以用結(jié)構(gòu)體(struct)組合在一起切威,以此來聲明新的數(shù)據(jù)類型育特;
- C 語言可以用 typedef 關(guān)鍵字來定義類型的別名,以此來達(dá)到變量類型的抽象先朦;
- C 語言是一個(gè)有結(jié)構(gòu)化程序設(shè)計(jì)缰冤、具有變量作用域以及遞歸功能的過程式語言;
- 通過指針喳魏,C 語言可以容易地對內(nèi)存進(jìn)行低級控制棉浸,然而這加大了編程復(fù)雜度;
- 編譯預(yù)處理讓 C 語言的編譯更具有彈性刺彩,比如跨平臺迷郑。
然而,在代碼組織和功能編程上创倔,C語言的上述嗡害,卻不那么美妙了,eq:
//一個(gè)簡單的交換兩個(gè)變量的函數(shù)
void changeVar(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
可以想一想畦攘,這里為什么要用指針呢霸妹?因?yàn)槿绻挥弥羔樀脑挘皇莻鬟M(jìn)來的行參念搬,即函數(shù)的形參是調(diào)用實(shí)參的一個(gè)拷貝抑堡,函數(shù)閉包里對形參的修改無法影響實(shí)參的結(jié)果摆出。
然而,這個(gè)函數(shù)最大的問題是int tmp = *x
決定了這個(gè)函數(shù)只能給int值使用首妖,但是還有好多類型也等著能被調(diào)用呢偎漫,eq:double、float有缆、string等象踊,這就是個(gè)靜態(tài)語言最糟糕的問題。
當(dāng)然棚壁,這個(gè)時(shí)候大家都會想到類型轉(zhuǎn)換杯矩,然而對于C語言的類型轉(zhuǎn)換,是會出現(xiàn)很多問題的袖外。
- 比如:一個(gè) double a[10] 的數(shù)組史隆,a[2] 意味著 a + sizeof(double) * 2。如果你把 a 強(qiáng)轉(zhuǎn)成 int曼验,那么 a[2] 就意味著 a + sizeof(int) * 2泌射。我們知道 sizeof(double) 是 8,而 sizeof(int) 是 4鬓照。于是訪問到了不同的地址和內(nèi)存空間熔酷,這就導(dǎo)致程序出現(xiàn)嚴(yán)重的問題。下面這種使用臨時(shí)交換數(shù)據(jù)的buffer拷貝方案可以去掉類型轉(zhuǎn)換時(shí)導(dǎo)致的地址變換:
//加入泛型變量的交換兩個(gè)變量的函數(shù)
void changeVar(void* x, void* y, size_t size)
{
char tmp[size]; //交換數(shù)據(jù)時(shí)需要用的 buffer
memcpy(tmp, y, size);
memcpy(y, x, size);
memcpy(x, tmp, size);
/**
* 1.函數(shù)接口中增加了一個(gè)size參數(shù)豺裆,用了 void* 后拒秘,類型被“抽象”掉了
,編譯器不能通過類型得到類型的長度了臭猜,所以躺酒,需要我們手動地加上一個(gè)類型長度的標(biāo)識。
2.函數(shù)的實(shí)現(xiàn)中使用了memcpy()函數(shù)蔑歌,因?yàn)轭愋捅弧俺橄蟆钡袅耍圆荒苡觅x值表達(dá)式了丐膝,很有可能傳進(jìn)來的參數(shù)類型還是一個(gè)結(jié)構(gòu)體,因此帅矗,為了要交換這些復(fù)雜類型的值,我們只能使用內(nèi)存復(fù)制的方法了煞烫。
*/
}
除了上面使用void* 來做泛型浑此,在C語言中,還可以用宏定義來做泛型凛俱,不過卻會帶來宏的字符串替換,導(dǎo)致代碼膨脹蒲犬,導(dǎo)致編譯出的執(zhí)行文件相對較大朱监,此處感興趣的可以去深入學(xué)習(xí)一下。