【C++避坑相關-僅供參考】純C語言的工作有前(錢)景嗎?
來源鏈接:韋易笑的回答
https://www.zhihu.com/answer/47513658

要不要黑一下 C++呢?呵呵呵。
------------------
咱們要有點娛樂精神,關于 C++的笑話數(shù)都數(shù)不清:
笑話:C++是一門不吉祥的語言,據(jù)說波音公司之前用ADA為飛機硬件編程,一直用的好好的,后來招聘了一伙大學生,學生們說我靠還在用這么落后的語言,然后換成C++重構后飛機就墜毀了。
笑話:什么是C++程序員呢?就是本來10行寫得完的程序,他非要用30行來完成,并自稱“封裝”,但每每到第二個項目的時候卻將80%打破重寫,并美其名曰 “重構”。
笑話:C容易擦槍走火打到自己的腳,用C++雖然不容易,但一旦走火,就會把你整條腿給炸飛了。
笑話:同時學習兩年 Java的程序員在一起討論的是面向對象和設計模式,而同時學習兩年 C++的程序員,在一起討論的是 template和各種語言規(guī)范到底怎么回事情。
笑話:教別人學 C++的人都掙大錢了,而很多真正用 C++的人,都死的很慘。
笑話:C++有太多地方可以讓一個人表現(xiàn)自己“很聰明”,所以使用C++越久的人,約覺得自己“很聰明”結果步入陷阱都不知道,掉坑里了還覺得估計是自己沒學好 C++。
笑話:好多寫了十多年 C++程序的人,至今說不清楚 C++到底有多少規(guī)范,至今仍然時不時的落入某些坑中。
笑話:很多認為 C++方便跨平臺的人,實際編寫跨平臺代碼時,都會發(fā)現(xiàn)自己難找到兩個支持相同標準的 C++編譯器。
---------------
Q:那 C++為什么還能看到那么多粉絲呢?
A:其實是因為 Windows,因為 Windows的興起帶動了 C++,C++本來就是一門只適合開發(fā) GUI的語言。
Q:為何 C++只適合開發(fā) GUI呢?
A:你看 Unix下沒有 GUI,為啥清一色的 C呀?所有的系統(tǒng)級問題都能在 C里找到成熟的解決方案,應用級問題都能用其他高級語言很好地解決,哪里有 C++什么事情呀?
Q:你強詞奪理,Unix下也有 C++的項目呀。
A:有,沒錯,你任然可以用任何語言編寫任何糟糕的代碼。
Q:別瞎扯了,你都在說些什么?連C++和 Windows 都扯到一起去了。
A:回想下當年的情景,一個大牛在教一群初學者如何編程。一邊開發(fā)一邊指著屏幕上說,你看,這是一個 Button,我們可以用一個對象來描述它,那是一個 panel我們也可以用一個對象來描述它,并且你們有沒有發(fā)現(xiàn),其實 Button和 Panel是有血緣關系的,你們看。。。這樣就出來了。。。。下面的學生以前都是學著學校落后的教材,有些甚至還在用 turboc的 bgi庫來畫一些點和圓。哪里見過這么這么華麗的 Windows 界面呀。大牛說的話,象金科玉律一樣的銘刻在自己幼小的心理。一邊學著 Windows,一邊發(fā)現(xiàn),果然,他們都需要一個基類,果然,他們是兄弟關系,共同包含一些基本屬性,可以放到基類去。他們越用越爽,潛意識里覺得因為 C++這么順利的幫他們解決那么多界面問題,那看來 C++可以幫他們解決一切問題了。于是開發(fā)完界面以后,他們繼續(xù)開發(fā),當他們碰到各種設計問題時,反而認為肯定自己沒有用好 C++。于是強迫自己用下去,然后就完蛋了。
---------------
關于 C++的笑話我有一籮筐,各位 C++粉用不著對號入座。言歸正傳,為什么要黑 C++呢?談不上黑不黑,我從94年開始使用 C++(先前是 C 和 Pascal),一路看著 C++成長壯大,用 C++寫過的代碼,加起來應該超過 10MB了吧,C++的各種寶典我也都讀過,一直到 2004年開始切回 C,主要原因是發(fā)現(xiàn)很多沒法用 C++思路繼續(xù)解決下去的問題,或者說用 C++思路解決下去會很糟糕的問題。
那時候(2004-2005)正是 C++滿天飛的時候,言必稱 C++,用必用模版,我跳出來說你們醒醒吧,別過火了,這個世界并不是都是抽象數(shù)據(jù)結構和算法就可以描述清楚的。于是很多人激動的跳出來說:“你沒領會到 C++精髓,你根本都不會用 C++”。我問他們:“語言是用來解決問題的,如果一個語言學了三四年都會經常掉溝里,算好語言么?如果編寫十多年 C++的程序員都很難掌握得了,這算好語言么”。他們又說:“語言是死的,人是活的”。
我記得當時一位國內 C++大牛,為了糾正我的 “錯誤觀點”,給我看過他寫的一套十分強大的庫,我打開一看,倒吸了一口冷氣,全部是 .h文件。我只能回他三個字:“你牛逼”。當然這是一個極端的例子,那家伙后來終于也開始把 .h里面的東西逐步挪到 .cpp里面了,這是好事。
當時和云風在一家公司,2004年新人培訓時,他給新人布置了一個實現(xiàn)內存分配器的作業(yè),批改作業(yè)的時候,他經常邊看邊問人家,“不夠C++呀,你能不能百分之百OOP?”,“1%的 C都不要留”。我當時在公司內部郵件列表里面發(fā)過關于 C++的問題,大部分人都表示:“你看沒有C++我們怎么寫3D引擎呢?”。我跟他們講:“John Carmack直到 Quake3都還在用著 ANSI C,后來因為不得不支持 D3D,改用 C++了。為啥 C不能寫 3D引擎了?”。他們告訴我:“你看,Point,就是個對象,Matrix也是個對象,那么多 Vector的代數(shù)計算,用 C++的算術重載是多么美妙的事情,三維世界就是對象的世界。”。
確實當時客戶端 GUI的話,只有 C++,圖形引擎也只有 C++,這兩個正是C++最強的地方,所以我也沒和他們爭辯,強迫他們承認 C也可以很漂亮的寫圖形,而且C寫的可以寫的很優(yōu)雅。我又不是閑著沒事情,何必去質疑人家的核心價值觀呢,呵呵。當年我正在接手一個 C++項目,代碼超過 800KB,每次崩潰都需要花費很長時間去定位,項目中大量的前后依賴,改一個地方,前后要看好幾處,一處遺漏,整個系統(tǒng)就傻逼了。我開始重構后,畫了兩個星期,將性能敏感的核心部分剝離出來用 C實現(xiàn)(代碼量僅 200KB),然后導出 Python接口,用Python來完成剩下的部分,整個腳本層代碼量只有 150KB。整個世界清爽了,整個 C++項目原來的工期為 2個程序員四個月,我一個人重構的時間加起來就 1.5個月,而且代碼量比遠來少了兩倍還多,各種奇特的 BUG也一掃而盡。我看看左邊的 800KB一團亂麻的 C++代碼,再看看右邊整潔的 300多 KB 純 C + Python,琢磨著,這個項目干嘛不一開始就這么做?
跨語言接口
現(xiàn)代項目開發(fā),不但需要更高的性能,而且需要更強大的語言描述能力。而 C++正處在一個尷尬的地方,比底層,它不如 C能夠精確的控制內存和硬件,各種隱式構造讓你防不勝防;比描述能力,比快速業(yè)務開發(fā)和錯誤定位,它又趕不上 Python, Ruby, Lua等動態(tài)語言,處于東線和西線同時遭受擠壓和蠶食的地步。
很快,2006-2007年左右,其他項目組各種濫用 C++的問題開始顯現(xiàn)出來:當時腳本化已經在工程實踐中獲得極大的成功,然而某些項目一方面又要追求 100%的 C++,另一方面又需要對腳本導出接口,他們發(fā)現(xiàn)問題了,不知道該怎么把大量的 C++基礎庫和接口導給 Lua。
C的接口有各種方便的方式導給腳本,然而整個項目由一群從來就不消于使用腳本的cpp大牛開發(fā)出來,當他們要吧cpp類導出接口給腳本時,他們設計了一套牛逼的系統(tǒng),lua自動生成機器碼,去調用c++的各種類,沒錯,就是c++版本的cffi或者ctypes。他為調用vc的類寫了一套機器碼生產,又為調用gcc的類寫了一套代碼生成。那位cpp大牛寫完后四處炫耀他的成果,后來他離職了,項目上線一而再再而三的出現(xiàn)無可查證的問題,后來云風去支援那個項目組,這套盤根錯節(jié)的c++項目,這套盤大的代碼自生成系統(tǒng)深深的把他給惡心到了。后來眾所周知云風開始反C++,倡導回歸C了,不知道是否和這個項目有關系。
于是發(fā)現(xiàn)個有趣的現(xiàn)象,但凡善于使用腳本來提高工程效率的人,基本都是C加動態(tài)語言解決大部分問題(除了gui和圖形),但凡認為c++統(tǒng)治宇宙的人很多都是從來沒使用過腳本或者用了還不知道該怎樣去用的人。
憑借這樣的方法,我們的產品同競爭對手比拼時,同樣一個功能,同樣的人力配置,競爭對手用純C++要開發(fā)三月,我們一個月就弄出來了,同樣的時間,對手只能試錯一次,我們可以試錯三次。后來,據(jù)我們招聘過來的同事說,競爭對手也開始逐步降低 C++的比例,增加 java的比例了,這是好事,大家都在進步嘛。
ABI的尷尬
ABI級別的 C++接口從來沒有標準化過,以類為接口會引入很多隱藏問題,比如內存問題,一個類在一個庫里面實例化的,如果再另外一個庫里面釋放它們就有很多問題,因為兩個動態(tài)庫可能內存管理系統(tǒng)是不一樣的。你用這里的 allocator分配一塊內存,又用那里的 allocator去釋放,不出問題才怪。很多解決方法是加一個 Release方法(比如 DX),告訴外面的人,用完的時候不要去 delete,而是要調用 Release。項目寫大了各個模塊隔離成動態(tài)庫是很正常的,而各種第三方庫和自己寫的庫為追求高性能引入特定的內存管理機制也是很正常的。很多人不注意該調用release的地方錯寫成delete就掉溝里去了。更有勝者跨 ABI定義了很多inline方法的類,結果各種隱式構造和析構其實在這個庫里生成,那個庫里被析構,亂成一團亂麻。C就清晰很多,構造你就調用fopen,析構你就fclose,沒有任何歧義。其實C++的矛盾在于一方面承認作為系統(tǒng)級語言內存管理應該交給用戶決定,一方面自己卻又定義很多不受用戶控制的內存操作行為。所以跨 ABI層的c++標準遲遲無法被定義出來,不是因為多態(tài) abi復雜,而是因為語言邏輯出現(xiàn)了相互矛盾。為了彌補這個矛盾,C++引入了operator new,delete,這new/delete重載是一個補丁并沒從邏輯上讓語言變得完備,它的出現(xiàn),進一步將使用者拖入bug的深淵。
其實今天我們回過頭去看這個問題,能發(fā)現(xiàn)兩個基本原則:跨abi的級別上引入不可控的內存機制從語言上是有問題的,只能要靠開發(fā)者約定各種靈巧的基類和約定開發(fā)規(guī)范來解決,這個問題在語言層是解決不了的;其次你既然定義了各種隱式構造和析構,就該像java活著動態(tài)語言一樣徹底接管內存,不允許用戶再自定義任何內存管理方法,而不是一方面作為系統(tǒng)極語言要給用戶控制的自由,一方面自己又要搶著和用戶一起控制。
因此對象層 ABI接口遲遲無法標準化。而純 C的 ABI不但可以輕松的跨動態(tài)庫還能輕松的和匯編及各類語言融合,不是因為C設計多好,而是C作為系統(tǒng)層語言沒有去管它不該管的東西。當年討論到這個話題時 C++大牛們又開始重復那幾句金科玉律來反駁我:“語言只是招式,你把內功練好,就能做到無招勝有招,拿起草來都可以當劍使,C++雖然有很多坑,你把設計做好不那么用不就行了”。我說:本來應該在語言層解決好的事情,由于語言邏輯不完備,將大量問題拋給開發(fā)者去解決極大的增加了開發(fā)者的思維負擔,就像破屋上表漿糊一樣。你金庸看多了吧,武術再高,當你拿到一把槍發(fā)現(xiàn)子彈不一定往前射,偶爾還會往后射時,請問你是該專心打敵人呢?還是時刻要提防自己的子彈射向自己?
系統(tǒng)層的挫敗
C++遭受挫敗是進軍嵌入式和操作系統(tǒng)這樣靠近硬件層的東西。大家覺得宇宙級別的編程語言,自然能夠勝任一切任務,很快發(fā)現(xiàn)幾個問題:
無法分配內存:原來用 C可以完全不依賴內存分配,代碼寫幾千行一個 malloc沒有都行。嵌入式下處理器加電后,跳到特定地址(比如起始地址0),第一條指令一般用匯編來寫,固定在0地址,就是簡單初始化一下棧,然后跳轉到 C語言的 start函數(shù)去,試想此時內存分配機制都還沒有建立,你定義了兩個類,怎么構造呀?資源有限的微處理器上大部分時候就是使用一塊靜態(tài)內存進行操作。C++寫起來寫爽了,各種隱式構造一出現(xiàn),就傻了。
標準庫依賴:在語言層面,C語言的所有特性都可以不用依賴任何庫就運行,這為編寫系統(tǒng)層和跨平臺跨語言代碼帶來了很方便的特性。而C++就不行,我要構造呀,我要異常呀,你能不給我強大的運行時呢?什么你還想用 stl?不看看那套庫有多臃腫呀(內存和代碼尺寸)。
異常處理問題:底層開發(fā)需要嚴格的處理所有錯誤返回,這一行調用,下一行就判斷錯誤。而異常是一種松散的錯誤處理方式,應用層這么寫沒問題,系統(tǒng)層這么寫就很狼狽了。每行調用都try一下和 C的調用后if判斷結果有什么區(qū)別?C++的構造函數(shù)是沒有返回值的,如果構造內部出錯,就必須逼迫你catch構造函數(shù)的異常,即便你catch住了,此時這個實例是一個半初始化實例,你該怎么處理它呢?于是有人把初始化代碼移除構造函數(shù),構造時只初始化一下變量,新增加一個帶返回的init函數(shù),這樣的代碼寫的比C冗余很多。何況硬件中斷發(fā)生時,在你不知道的情況下,同事調到一些第三方的庫,你最外層沒有把新的exception給 catch住,這個exception該往哪里拋呀?內存不夠的時候你想拋出一個 OutOfMemoryException,可是內存已經不夠了,此時完全無能力構造這個異常又該怎么辦呢?
處理器兼容:C++的類依賴基地址+偏移地址的尋址方式,很多微處理器只有簡單的給定地址尋址,不支持這樣一條語句實現(xiàn)BASE+OFFSET的尋址,很多C++代碼編譯出來需要更多的指令來運算地址,導致性能下降很多,得不償失。
隱式操作問題:C的特點是簡單直接,每行語句你都能清楚的知道會被翻譯成什么樣子,系統(tǒng)會嚴格按照你的代碼去執(zhí)行。而用C++,比如 str1 = str2 + "Hello" + str3; 這樣的語句,沒幾個人真的說得清楚究竟有多少次構造和拷貝,這樣的寫法編寫底層代碼是很不負責任的,底層需要更為精細和嚴格的控制,用C語言控制力更強。
當然,說道這里很多人又說,“C++本來就是 C的超集,特定的地方你完全可以按照C的寫法來做呀。沒人強迫你構造類或者使用異常呀”,沒錯,按 Linus的說法:“想要用C++寫出系統(tǒng)級的優(yōu)秀的可移植和高效的代碼,最終還是會限于使用C本身提供的功能,而這些功能C都已經完美提供了,所以系統(tǒng)層使用C的意義就在于在語言層排除C++的其他特性的干擾”。
很多人都記得 Linus在 2007年因為有人問 Git為什么不用 C++開發(fā)炮轟過一次C++。事實上2004年 C++如日中天的時候,有人問 Linux內核為何不用 C++開發(fā),他就炮轟過一次了:
實際上,我們在1992年就嘗試過在Linux使用 C++了。很惡心,相信我,用C++寫內核是一個 “BLOODY STUPID IDEA”。事實上,C++編譯器不值得信任,1992年時它們更糟糕,而一些基本的事實從沒改變過:
- 整套 C++異常處理系統(tǒng)是 “fundamentally broken”。特別對于編寫內核而言。
- 任何語言或編譯器喜歡在你背后隱藏行為(如內存分配)對于開發(fā)內核并不是一個好選擇。
- 任然可以用 C來編寫面向對象代碼(比如文件系統(tǒng)),而不需要用 C++寫出一坨屎來。
總得來說,對任何希望用 C++來開發(fā)內核的人而言,他們都是在引入更多問題,無法象 C一樣清晰的看到自己到底在寫什么。
C++粉絲們在C++最火熱的時候試圖將 C++引入系統(tǒng)層開發(fā),但是從來沒有成功過。所以不管是嵌入式,還是操作系統(tǒng),在靠近硬件底層的開發(fā)中,都是清一色的 C代碼,完全沒有 C++的立足之地。
應用層的反思
STL出來后,給人一種 C++可以方便開發(fā)應用層邏輯的錯覺。由于很多語言層不嚴密的事情,讓STL來以補丁的方式完成,于是很多以為可以象寫 java一樣寫 C++的初學者落入了一個個的坑中。比如 list.size(),在 Windows下vc的 stl是保存了 list的長度的,size()直接 O(1)返回該變量,而在gcc的 stl中,沒有保存 list長度,size()將搜索所有節(jié)點,O(n)的速度返回。
由于語言層不支持字符串,導致 std::string實現(xiàn)十分不統(tǒng)一,你拷貝構造一個字符串,有的實現(xiàn)是引用,才用 copy-on-write的方法引用。有的地方又是 new,有的實現(xiàn)又是用的內存池,有的實現(xiàn)線程安全,有的實現(xiàn)線程不安全,你完全沒法說出同一個語句后面到底做了些什么(見孟巖的《Linux之父話糙理不糙》)。
再比如說我想使用 hash_map,為了跨平臺(當你真正編寫跨平臺代碼時,你很難決定目標編譯器和他們的版本,想用也用不了 unordered_map),我很難指出一種唯一聲明 hash_map的方法,為了保證在不同的編譯器下正常的使用 hash_map,你不得不寫成這樣:
#ifdef __GNUC__
#ifdef __DEPRECATED
#undef __DEPRECATED
#endif
#include <ext/hash_map>
namespace stdext { using namespace __gnu_cxx; }
namespace __gnu_cxx {
template<> struct hash< std::string > {
size_t operator()( const std::string& x ) const {
return hash< const char* >()( x.c_str() );
}
};
}
#else
#ifndef _MSC_VER
#include <hash_map>
#elif (_MSC_VER < 1300)
#include <map>
#define IHAVE_NOT_HASH_MAP
#else
#include <hash_map>
#endif
#endif
#ifdef __GNUC__
using namespace __gnu_cxx;
typedef hash_map<uint32_t, XXXX*> HashXXXX;
#else
using namespace stdext;
typedef hash_map<uint32_t, XXXX*> HashXXXX;
#endif
如果有更好的跨平臺寫法,麻煩告訴我一下,實在是看不下去了。一個基礎容器都讓人用的那么辛苦,使得很多 C++程序員成天都在思考各種規(guī)范,沒時間真正思考下程序設計。
由于語言層要兼容 C,又不肯象 C一樣只做好系統(tǒng)層的工作,導致當 C++涉足應用層時,沒法接管內存管理,沒法支持語言層字符串,沒法實現(xiàn)語言層基礎容器。所以需要借助一些 stl之類的東西來提供便利,但 stl本身又是充滿各種坑的。且不說內存占用大,程序體積大等問題,當編譯速度就夠嗆了。所以為什么 C++下面大家樂意重復造輪子,實現(xiàn)各種基本容器和字符串,導致幾乎每個不同的 C++項目,都有自己特定的字符串實現(xiàn)。就是因為大家踩了坑了,才開始覺得需要自己來控制這些細節(jié)。stl的出發(fā)點是好的,但是只能簡單小程序里面隨便用一下,真是大項目用,stl就容易把人帶溝里了,所以很多大點的 C++項目都是自己實現(xiàn)一套類似 STL的東西,這難道不是違背了 stl設計的初衷了么?
語言層的缺失,讓大家為了滿足業(yè)務開發(fā)的快速迭代的需求,創(chuàng)造了很多很
基礎的設計靈巧的基類,來提供類似垃圾回收,引用計數(shù),copy-on-write,delegate,等數(shù)不勝數(shù)的功能。每個項目都有一系列 BaseObject 之類的基礎類,這樣就引入一個誤區(qū),兩年后你再來看你的代碼,發(fā)現(xiàn)某個 BaseObject不滿足需求了,或者你和另外一個項目 merge代碼時,需要合并一些根本屬性。圖形和GUI這些萬年不變的模型還好,應用類開發(fā)千變萬化,一旦這些設計靈巧的基類不再適應項目發(fā)展時,往往面臨著全面調整的代價。
打開一個個 C++大牛們 blog,很多地方在教你 std::string的原理,需要注意的事項。map的限制,vector的原理,教你如何實現(xiàn)一個 string。這就叫 “心智負擔”,分散你的注意力,這是其他語言里從來見不到的現(xiàn)象。戰(zhàn)士不研究怎么上前線殺敵,天天在琢磨搶和炮的原理,成天在思考怎么用槍不會走火,用炮不會炸到自己,這戰(zhàn)還怎么打?
所以此后幾年,越來越多的人開始反思前兩年C++過熱所帶來的問題,比如高性能網絡庫 ZeroMQ作者 Martin Sustrik 的:《為什么我希望用C而不是C++來實現(xiàn)ZeroMQ》,比如云風的《云風的 BLOG: C 的回歸》,比如引起熱議的《Why C++ Is Not "Back"》。
全面被代替
2008年以后,行業(yè)競爭越來越激烈,正當大家一邊苦惱如何提高開發(fā)效率,一邊掉到C++的各種坑里的時候,越來越多的應用開發(fā)方案涌現(xiàn)出來,他們都能很好的代替 C++。各行各業(yè)的開發(fā)者逐步相見恨晚的發(fā)現(xiàn)了各種更加優(yōu)秀的方案:需要底層控制追求性能的設計,大家退回到 C;而需要快速迭代的東西大家找到各種動態(tài)語言;介于性能和開發(fā)速度之間的,有java,知乎上好像很多黑java的,語言是有不足,但是比起C++好很多,沒那么多坑,真正考慮面向對象,真正讓人把心思放在設計上。所以再黑也不能擋住 java在 tiobe上和 C語言不是第一就是第二的事實,再黑也擋不住 java在云計算,分布式領域的卓越貢獻。

所以2005年以后,C++處在一個全面被代替的過程中:
底層系統(tǒng):進一步回歸 C語言,更強的控制力,更精確的操作。
網頁開發(fā):2006年左右,C++和 fastcgi就被一起趕出 web世界了。
高性能服務:varnish, nginx, redis 等新的高性能網絡服務器都是純C開發(fā)的。
分布式應用:2007年左右, C++被java和其他動態(tài)語言徹底趕跑。
游戲服務端:2008年后進一步進化為 C 和 腳本,完全看不到胖C++服務端了。
并行計算:2010年后,go, scala, erlang;而能方便同go接口的,是 C不是C++。
游戲引擎:沒錯 C++和腳本,但是這年頭越來越多的開源引擎下,引擎類需求越來越少。
游戲邏輯:腳本
多媒體:SDL純C,ffmpeg是純 C,webrtc的核心部分(DSP, codec)是純C的。
移動開發(fā):早年C++還可以開發(fā)下塞班,現(xiàn)在基本被 java + objc + swift 趕跑了。
桌面開發(fā):Qt+Script, C#等都能做出漂亮的跨平臺界面。且界面腳本化趨勢,不需要C++了。
網頁前端:JavaScript, Html5, Flash
操作系統(tǒng):FreeBSD, Open Solaris, Linux, RTOS, Darwin(OS X 底層),都是純 C
虛擬技術:qemu / kvm (云計算的基石)純 C,Xen 純 C
數(shù)據(jù)庫:MySQL (核心純C,外圍工具 C++),SQLite 純 C, PostgreSQL / BDB / unqlite 純C
編譯器:C/C++并存,不過編譯器用腳本寫都沒關系,我還在某平臺用 java寫的 C/C++編譯器
大數(shù)據(jù):kafka, hadoop, storm, spark 都使用 Java
云存儲:openstack swift python, hdfs java, 還有好多方案用 go
可以看出,即便 C++的老本行,GUI和圖形(確實也還存在一些短期內 C++無法替代的領域,就像交易統(tǒng)里還有 COBOL一樣),這年頭也面臨的越來越多的挑戰(zhàn),比如新發(fā)布的 Rust (如何看待 Rust 的應用前景? - 知乎用戶的回答)。可以發(fā)現(xiàn),開發(fā)技術多元化,用最適合的技術開發(fā)最適合的應用是未來的趨勢。而為這些不同的技術編寫高性能的可控的公共組件,并輕松的和其他語言接口,正是 C語言的強項。所以不管應用層語言千變萬化,對系統(tǒng)級開發(fā)語言C的需求還是那么的穩(wěn)定,而這個過程中,哪里還有 C++的影子呢?
話題總結
所以說未來的趨勢是:C x 各種語言混搭 的趨勢,從TIOBE上 C++的指數(shù)十年間下跌了三倍可以看出,未來還會涌現(xiàn)出更多技術來代替各個角落殘存的C++方案,C++的使用情況還會進一步下降。所以題主問學習純C是否有前途,我覺得如果題主能夠左手熟練的掌握 C語言,培養(yǎng)系統(tǒng)化的思維習慣和精確控制內存和硬件的技巧;右手繼續(xù)學習各種新興的開發(fā)技術,能夠應對各個細分領域的快速開發(fā),碰到新問題時能左右開弓,那么未來工作上肯定是能上一個大臺階的。至于C++ 嘛,有時間看看就行,逼不得已要維護別人代碼的情況下寫兩行即可。
故事分享
古代用弓箭進行遠距離攻擊時,對射手要求較高,瞄準難度大,需要一直使勁保持準心。戰(zhàn)斗中一個弓箭手開弓二十次就需要比較長的休息時間。弩的威力遠勝于弓,秦弩的制造就如現(xiàn)代的自動步槍一般精密無二,它既可以延長射擊,又可以精確瞄準。弩箭的發(fā)射速度更是弓箭的數(shù)倍,威力驚人。因為弩的操作非常簡單,不需要射擊技巧,平民很容易掌握它的使用方法。秦國靠著弩兵,在戰(zhàn)爭中取得了不少優(yōu)勢,被人稱為 “虎狼之師”。
日本投降時,天皇下罪己詔。很多士兵不愿意相信這時真的,找種種理由拒絕相信。有的士兵甚至以為天皇的廣播是敵人誘降的把戲,于是躲到叢林里繼續(xù)三五成群的收集情報,襲擊可以攻擊的目標,等待上司來給他們下達新命令。直到好幾年后看到周圍的人都穿著日常的便裝了,而來巡山的 “敵人” 也從士兵變?yōu)榱搜策夑?,他們都還覺得這是敵人的偽裝。而同時,德國戰(zhàn)敗時,最后的黨衛(wèi)軍一直戰(zhàn)斗到 1957年才肯投降。
-----------------------------------------
很多人覺得 java慢,C++快java 10倍以上已經是上世紀的事情了,現(xiàn)代的 java 只比 C/C++慢 70%,C++連1倍都快不了 java。也不要覺得動態(tài)語言慢,javascript只比C/C++慢 2.7倍。luajit只比 C++慢 5.8倍。在 jit技術發(fā)展的今天,C++在性能上離動態(tài)語言/java的差距越來越小,可易用性和生產效率上的差距,卻和動態(tài)語言/java 比起來越來越大。

---------------------------
最后,補充一張圖:
