純C語言的工作有前(錢)景嗎?
實習,有個純C語言開發底層系統的offer,公司是創業公司,創始人有矽谷背景。這個offer應該接受嗎?純C的開發以後轉行去其他公司容易嗎?
補充:
首先謝謝各位熱心的回答。
另外補充一些信息:公司是個創業公司,而我只是去實習一年,並且還不確定以後做不做底層。
可以,以後智能硬體會有比較大的好處。不過說實話,一般來說不太可能只會一門語言啊。
C,C++干High-Performance的活,Python/Ruby做工具鏈,Javascript/C#/Java用於做界面和交互,SQL之類的DSL也要根據要求多多少少會一點。
@符茂松 指出我的說法太模糊了,說C和C++並不是要做「高性能」,而是要做「資源緊缺,並且希望性能非常Predicatable的活」。
嗯。的確是我的描述不精準,因為很多大規模、靠增加計算資源就能完成的計算任務,並不適合用C++去做,Java、C#、Erlang等都要更實用一些。
這個觀點我在答案的後半段、評論和其他答案的評論下也有一些提及。
整體來說,C和C++的目的並不完全是為了壓榨性能極限,更重要的是可預測性。比如說,程序用了10M內存,那就真真切切是10M;需要10ms做完這件事情,那隻要OS分配10ms就一定能做完,即便是內存分配和釋放的時間也是有界的。沒有GC來打斷,也沒有VM的隱性和不可控的開銷在其中。
如果任務需要達到計算單元極限的90%,只要肯花功夫總是能找到特定的表達滿足這一需求。
這才是C/C++,以及未來的Rust有競爭力的地方。
-------------------------------------------------------------------------------------------
不知道為什麼C和C++的聖戰又打了起來。地球上最佳的語言不是已經說好了 拍黃片 嗎?一群Loser在一起打架哪裡有什麼意思可言。
同樣的活,相同的運行效率,C++的抽象程度還是要好很多。如果吃不準可以少用一些複雜的特性就好。
很多人以跨語言為由否認C++作為零運行時代價、中等抽象語言的存在價值,也以為跨語言就是最好的方案。但是要知道Inter-language帶來的問題,不比它解決的問題少,一般來說,語言內抽象總是更好的選擇。我不看好C+腳本就能取代C++。取代C++的倒更有可能是Rust這樣經過重新設計後的靜態語言。
從現在來看,大型和中型軟體,OS,工業軟體,設計類軟體,除了C++外,真沒有特別好的選擇。其他市場的退縮不代表C++在核心領域沒有競爭力。在System領域,C和C++一直都是七三開。與其說是C++語言的問題,不如說是因為人才結構的問題。只要引入合適的C++要素,Object-based Programming,Interface,Type-Strict Programming,RAII,代碼就會得到顯著的改善。既然有人提到了Carmark,那麼DOOM就是個最好的例子。D3D不是選擇C++的理由,C一樣可以調用COM組件。更別說試圖C++化的GCC和一開始就從C++開始的LLVM。作為編譯器的作者,他們總是會比一般人更加清楚語言的特性和優缺點。
而C++在一些非單一計算單位性能相關的市場,比如Web Server,因為gc類語言額外開銷和平台計算能力不彰歷史原因,導致C++曾經被用在了這些領域。這一領域的退縮本來就是理所當然的,因為這塊蛋糕本來就不是你應該吃的。至於Nginx,他用C++的話應該會寫出一個代碼更少,結構更緊湊的Nginx吧。
我不說別的,沒有歷史包袱的LLVM不只做C的Front-End,而非要吃力不討好的做個C++的Front-End呢?
顯然是有需求的。
-------------------------------------------------------------------------------
說個題外話,一個以來我都覺得有一個現象很有趣,就是大家在黑一類編程範式的時候,似乎從不關心他們為什麼被設計成那個樣子。在學統計的時候,就有人將一個教誨對我重複了無數遍:一定要搞清楚模型的Pre-condition。任何一個能發明被大家所接受的模型的人,都不可能比你更傻。
比如很多人黑OOP的Design Pattern太多,是個「沒有必要的心智負擔」。誠然,很多時候,只要Ducking Type就能解決Design Pattern費盡心力想要處理的解耦問題,卻全然沒想過,Ducking Type是以犧牲了編譯期檢查和運行時性能的代價換來的。Design Pattern是在需要解耦的時候,給了你一個可操作性很強的方法,在不需要的時候,你大可以忽略它。
作為一個特例,他當然可以說,DP對他來說就是Bullshit。但是他不可能永遠都活在一個特例里。這些「代價」的取捨,才是選型的關鍵所在。如果想不清楚這一點,用什麼語言都不能解決他是一個傻逼的本質。
題主問的是純C,結果下面一票人狂黑C++,這是怎樣一種精神病啊……
給題主一個切題的答案吧,單純用C的工作現在很少,主要集中在嵌入式和OS內核這些地方,而且市場還在不停地萎縮,因為即便是嵌入式系統,CPU也是越來越強勁,內存也越來越大,很多原來直接在裸機上開發的工作現在已經轉移到訂製Linux系統上來了,剩下的工作也就是寫寫驅動或加幾個內核模塊了。還有一個多用C的領域是與各種腳本集成,但如果你不熟悉這些腳本語言的介面規範這活也是不容易干好的,而且這個領域還有C++來搶地盤,Rust也算是個潛在的競爭對手。
編譯器虛擬機這一類的工作崗位太少,已有的項目也大多用C++或Java了,新語言的編譯器也流行自操哦不自舉,畢竟用C操幾十萬上百萬行代碼心智負擔太重。
還有一些熱門的領域,大數據用的是Java/Scala/Python/R,Web開發用的是Java和各種腳本語言,手機app用的是Java(Android)和Objective-C/Swift(iOS),服務端倒是有一些用C的活,但問題是從頭開發一個nginx或者redis的項目怕是你碰不上。
總之「純C」作為工作發展的方向不是很理想,但精通C對你學其它東西是非常有幫助的。
我對純 C 開發本身沒有負面感覺。相反我很喜歡 Linux kernel 之類的項目。但是如果一個職業框上一個「純 C」的框框,那說明編程的平台本身功能是比較弱的。或者需要跨平台比較多,解決的問題比較抽象也比較 well-defined,比如像 OS kernel,或者語言 VM。這種 well-defined 的抽象問題,一般都是 solved problem。競爭激烈,也沒有很多創新空間。
所以或者平台本身功能是比較弱的,或者是競爭激烈,也沒有很多創新空間的 well-defined 問題,我不太看好就業前景。作為一個老碼農,工作以後用到的語言總得有十種以上了吧,不要在意語言問題,關注行業和公司本身吧。在一個公司呆久了,也有可能用到多種語言的。
有了一兩個語言的基礎後,學新語言非常快。現在有些編程語言非常的相似。如果你現在就想打好基礎的話,學c/c++是不會錯的,這兩個本身是用途特別廣泛的語言。而且這兩種語言比較複雜,學會以後,你再學其他語言會有一種學習c/c++子集的感覺。
所有過程式的語言可以從c找到借鑒,而OO語言都與c++有很多相似點。
還有一種腳本型的語言,如linux shell,python,就是不用編譯,直接寫完就跑的,這種在工作中也很有用。可以學一下python,跨平台,功能強大。
So,關鍵看公司是否靠譜,行業是否有前途就好了。語言的問題不能指望公司教你,自學2-3種有用的語言吧。
需求決定前景,而不是語言吧。語言只是需求實現的產物。
依次玩過C,C++,PHP,NodeJS,ObjectiveC,Java,Swift。以前覺得自己好牛逼,做了10多年開發,逢求職必寫上自己的各種牛逼能力,後來發現,屁用都沒有。甚至以前我還寫自己做過多媒體編解碼,機頂盒應用,Windows和Linux的桌面應用,手機應用,一概列上。可發現那對工資也是沒啥提高。
所以最後我學乖了,只寫iOS軟體開發,偶爾做Android開發。其它就不提了,因為我突然明白,公司需要的不是我有多牛逼,而是我能夠為公司賺多少錢。
---------上述是打工的狀態,現在自己創業中。更是對什麼語言什麼技術毫無特別關注,我只要實現我的目標即可。
要不要黑一下 C++呢?呵呵呵。
------------------
咱們要有點娛樂精神,關於 C++的笑話數都數不清:
笑話:C++是一門不吉祥的語言,據說波音公司之前用ADA為飛機硬體編程,一直用的好好的,後來招聘了一夥大學生,學生們說我靠還在用這麼落後的語言,然後換成C++重構後飛機就墜毀了。
笑話:什麼是C++程序員呢?就是本來10行寫得完的程序,他非要用30行來完成,並自稱「封裝」,但每每到第二個項目的時候卻將80%打破重寫,並美其名曰 「重構」。
笑話:C容易擦槍走火打到自己的腳,用C++雖然不容易,但一旦走火,就會把你整條腿給炸飛了。
笑話:同時學習兩年 Java的程序員在一起討論的是面向對象和設計模式,而同時學習兩年 C++的程序員,在一起討論的是 template和各種語言規範到底怎麼回事情。
笑話:教別人學 C++的人都掙大錢了,而很多真正用 C++的人,都死的很慘。
笑話:C++有太多地方可以讓一個人表現自己「很聰明」,所以使用C++越久的人,約覺得自己「很聰明」結果步入陷阱都不知道,掉坑裡了還覺得估計是自己沒學好 C++。
笑話:好多寫了十多年 C++程序的人,至今說不清楚 C++到底有多少規範,至今仍然時不時的落入某些坑中。
笑話:很多認為 C++方便跨平台的人,實際編寫跨平台代碼時,都會發現自己難找到兩個支持相同標準的 C++編譯器。
---------------
Q:那 C++為什麼還能看到那麼多粉絲呢?
A:其實是因為 Windows,因為 Windows的興起帶動了 C++,C++本來就是一門只適合開發 GUI的語言。
Q:為何 C++只適合開發 GUI呢?
A:你看 Unix下沒有 GUI,為啥清一色的 C呀?所有的系統級問題都能在 C里找到成熟的解決方案,應用級問題都能用其他高級語言很好地解決,哪裡有 C++什麼事情呀?
Q:你強詞奪理,Unix下也有 C++的項目呀。
A:有,沒錯,你任然可以用任何語言編寫任何糟糕的代碼。
Q:別瞎扯了,你都在說些什麼?連C++和 Windows 都扯到一起去了。
A:回想下當年的情景,一個大牛在教一群初學者如何編程。一邊開發一邊指著屏幕上說,你看,這是一個 Button,我們可以用一個對象來描述它,那是一個 panel我們也可以用一個對象來描述它,並且你們有沒有發現,其實 Button和 Panel是有血緣關係的,你們看。。。這樣就出來了。。。。下面的學生以前都是學著學校落後的教材,有些甚至還在用 turboc的 bgi庫來畫一些點和圓。哪裡見過這麼這麼華麗的 Windows 界面呀。大牛說的話,象金科玉律一樣的銘刻在自己幼小的心理。一邊學著 Windows,一邊發現,果然,他們都需要一個基類,果然,他們是兄弟關係,共同包含一些基本屬性,可以放到基類去。他們越用越爽,潛意識裡覺得因為 C++這麼順利的幫他們解決那麼多界面問題,那看來 C++可以幫他們解決一切問題了。於是開發完界面以後,他們繼續開發,當他們碰到各種設計問題時,反而認為肯定自己沒有用好 C++。於是強迫自己用下去,然後就完蛋了。
---------------
關於 C++的笑話我有一籮筐,各位 C++粉用不著對號入座。言歸正傳,為什麼要黑 C++呢?談不上黑不黑,我從94年開始使用 C++(先前是 C 和 Pascal),一路看著 C++成長壯大,用 C++寫過的代碼,加起來應該超過 10MB了吧,C++的各種寶典我也都讀過,一直到 2004年開始切回 C,主要原因是發現很多沒法用 C++思路繼續解決下去的問題,或者說用 C++思路解決下去會很糟糕的問題。
那時候(2004-2005)正是 C++滿天飛的時候,言必稱 C++,用必用模版,我跳出來說你們醒醒吧,別過火了,這個世界並不是都是抽象數據結構和演算法就可以描述清楚的。於是很多人激動的跳出來說:「你沒領會到 C++精髓,你根本都不會用 C++」。我問他們:「語言是用來解決問題的,如果一個語言學了三四年都會經常掉溝里,算好語言么?如果編寫十多年 C++的程序員都很難掌握得了,這算好語言么」。他們又說:「語言是死的,人是活的」。
我記得當時一位國內 C++大牛,為了糾正我的 「錯誤觀點」,給我看過他寫的一套十分強大的庫,我打開一看,倒吸了一口冷氣,全部是 .h文件。我只能回他三個字:「你牛逼」。當然這是一個極端的例子,那傢伙後來終於也開始把 .h裡面的東西逐步挪到 .cpp裡面了,這是好事。
當時和雲風在一家公司,2004年新人培訓時,他給新人布置了一個實現內存分配器的作業,批改作業的時候,他經常邊看邊問人家,「不夠C++呀,你能不能百分之百OOP?」,「1%的 C都不要留」。我當時在公司內部郵件列表裡面發過關於 C++的問題,大部分人都表示:「你看沒有C++我們怎麼寫3D引擎呢?」。我跟他們講:「John Carmack直到 Quake3都還在用著 ANSI C,後來因為不得不支持 D3D,改用 C++了。為啥 C不能寫 3D引擎了?」。他們告訴我:「你看,Point,就是個對象,Matrix也是個對象,那麼多 Vector的代數計算,用 C++的算術重載是多麼美妙的事情,三維世界就是對象的世界。」。
確實當時客戶端 GUI的話,只有 C++,圖形引擎也只有 C++,這兩個正是C++最強的地方,所以我也沒和他們爭辯,強迫他們承認 C也可以很漂亮的寫圖形,而且C寫的可以寫的很優雅。我又不是閑著沒事情,何必去質疑人家的核心價值觀呢,呵呵。當年我正在接手一個 C++項目,代碼超過 800KB,每次崩潰都需要花費很長時間去定位,項目中大量的前後依賴,改一個地方,前後要看好幾處,一處遺漏,整個系統就傻逼了。我開始重構後,畫了兩個星期,將性能敏感的核心部分剝離出來用 C實現(代碼量僅 200KB),然後導出 Python介面,用Python來完成剩下的部分,整個腳本層代碼量只有 150KB。整個世界清爽了,整個 C++項目原來的工期為 2個程序員四個月,我一個人重構的時間加起來就 1.5個月,而且代碼量比遠來少了兩倍還多,各種奇特的 BUG也一掃而盡。我看看左邊的 800KB一團亂麻的 C++代碼,再看看右邊整潔的 300多 KB 純 C + Python,琢磨著,這個項目幹嘛不一開始就這麼做?
跨語言介面
現代項目開發,不但需要更高的性能,而且需要更強大的語言描述能力。而 C++正處在一個尷尬的地方,比底層,它不如 C能夠精確的控制內存和硬體,各種隱式構造讓你防不勝防;比描述能力,比快速業務開發和錯誤定位,它又趕不上 Python, Ruby, Lua等動態語言,處於東線和西線同時遭受擠壓和蠶食的地步。
很快,2006-2007年左右,其他項目組各種濫用 C++的問題開始顯現出來:當時腳本化已經在工程實踐中獲得極大的成功,然而某些項目一方面又要追求 100%的 C++,另一方面又需要對腳本導出介面,他們發現問題了,不知道該怎麼把大量的 C++基礎庫和介面導給 Lua。
C的介面有各種方便的方式導給腳本,然而整個項目由一群從來就不消於使用腳本的cpp大牛開發出來,當他們要吧cpp類導出介面給腳本時,他們設計了一套牛逼的系統,lua自動生成機器碼,去調用c++的各種類,沒錯,就是c++版本的cffi或者ctypes。他為調用vc的類寫了一套機器碼生產,又為調用gcc的類寫了一套代碼生成。那位cpp大牛寫完後四處炫耀他的成果,後來他離職了,項目上線一而再再而三的出現無可查證的問題,後來雲風去支援那個項目組,這套盤根錯節的c++項目,這套盤大的代碼自生成系統深深的把他給噁心到了。後來眾所周知雲風開始反C++,倡導回歸C了,不知道是否和這個項目有關係。
於是發現個有趣的現象,但凡善於使用腳本來提高工程效率的人,基本都是C加動態語言解決大部分問題(除了gui和圖形),但凡認為c++統治宇宙的人很多都是從來沒使用過腳本或者用了還不知道該怎樣去用的人。
憑藉這樣的方法,我們的產品同競爭對手比拼時,同樣一個功能,同樣的人力配置,競爭對手用純C++要開發三月,我們一個月就弄出來了,同樣的時間,對手只能試錯一次,我們可以試錯三次。後來,據我們招聘過來的同事說,競爭對手也開始逐步降低 C++的比例,增加 java的比例了,這是好事,大家都在進步嘛。
ABI的尷尬
ABI級別的 C++介面從來沒有標準化過,以類為介面會引入很多隱藏問題,比如內存問題,一個類在一個庫裡面實例化的,如果再另外一個庫裡面釋放它們就有很多問題,因為兩個動態庫可能內存管理系統是不一樣的。你用這裡的 allocator分配一塊內存,又用那裡的 allocator去釋放,不出問題才怪。很多解決方法是加一個 Release方法(比如 DX),告訴外面的人,用完的時候不要去 delete,而是要調用 Release。項目寫大了各個模塊隔離成動態庫是很正常的,而各種第三方庫和自己寫的庫為追求高性能引入特定的內存管理機制也是很正常的。很多人不注意該調用release的地方錯寫成delete就掉溝里去了。更有勝者跨 ABI定義了很多inline方法的類,結果各種隱式構造和析構其實在這個庫里生成,那個庫里被析構,亂成一團亂麻。C就清晰很多,構造你就調用fopen,析構你就fclose,沒有任何歧義。其實C++的矛盾在於一方面承認作為系統級語言內存管理應該交給用戶決定,一方面自己卻又定義很多不受用戶控制的內存操作行為。所以跨 ABI層的c++標準遲遲無法被定義出來,不是因為多態 abi複雜,而是因為語言邏輯出現了相互矛盾。為了彌補這個矛盾,C++引入了operator new,delete,這new/delete重載是一個補丁並沒從邏輯上讓語言變得完備,它的出現,進一步將使用者拖入bug的深淵。
其實今天我們回過頭去看這個問題,能發現兩個基本原則:跨abi的級別上引入不可控的內存機制從語言上是有問題的,只能要靠開發者約定各種靈巧的基類和約定開發規範來解決,這個問題在語言層是解決不了的;其次你既然定義了各種隱式構造和析構,就該像java活著動態語言一樣徹底接管內存,不允許用戶再自定義任何內存管理方法,而不是一方面作為系統極語言要給用戶控制的自由,一方面自己又要搶著和用戶一起控制。
因此對象層 ABI介面遲遲無法標準化。而純 C的 ABI不但可以輕鬆的跨動態庫還能輕鬆的和彙編及各類語言融合,不是因為C設計多好,而是C作為系統層語言沒有去管它不該管的東西。當年討論到這個話題時 C++大牛們又開始重複那幾句金科玉律來反駁我:「語言只是招式,你把內功練好,就能做到無招勝有招,拿起草來都可以當劍使,C++雖然有很多坑,你把設計做好不那麼用不就行了」。我說:本來應該在語言層解決好的事情,由於語言邏輯不完備,將大量問題拋給開發者去解決極大的增加了開發者的思維負擔,就像破屋上表漿糊一樣。你金庸看多了吧,武術再高,當你拿到一把槍發現子彈不一定往前射,偶爾還會往後射時,請問你是該專心打敵人呢?還是時刻要提防自己的子彈射向自己?
系統層的挫敗
C++遭受挫敗是進軍嵌入式和操作系統這樣靠近硬體層的東西。大家覺得宇宙級別的編程語言,自然能夠勝任一切任務,很快發現幾個問題:
- 無法分配內存:原來用 C可以完全不依賴內存分配,代碼寫幾千行一個 malloc沒有都行。嵌入式下處理器加電後,跳到特定地址(比如起始地址0),第一條指令一般用彙編來寫,固定在0地址,就是簡單初始化一下棧,然後跳轉到 C語言的 start函數去,試想此時內存分配機制都還沒有建立,你定義了兩個類,怎麼構造呀?資源有限的微處理器上大部分時候就是使用一塊靜態內存進行操作。C++寫起來寫爽了,各種隱式構造一出現,就傻了。
- 標準庫依賴:在語言層面,C語言的所有特性都可以不用依賴任何庫就運行,這為編寫系統層和跨平台跨語言代碼帶來了很方便的特性。而C++就不行,我要構造呀,我要異常呀,你能不給我強大的運行時呢?什麼你還想用 stl?不看看那套庫有多臃腫呀(內存和代碼尺寸)。
- 異常處理問題:底層開發需要嚴格的處理所有錯誤返回,這一行調用,下一行就判斷錯誤。而異常是一種鬆散的錯誤處理方式,應用層這麼寫沒問題,系統層這麼寫就很狼狽了。每行調用都try一下和 C的調用後if判斷結果有什麼區別?C++的構造函數是沒有返回值的,如果構造內部出錯,就必須逼迫你catch構造函數的異常,即便你catch住了,此時這個實例是一個半初始化實例,你該怎麼處理它呢?於是有人把初始化代碼移除構造函數,構造時只初始化一下變數,新增加一個帶返回的init函數,這樣的代碼寫的比C冗餘很多。何況硬體中斷髮生時,在你不知道的情況下,同事調到一些第三方的庫,你最外層沒有把新的exception給 catch住,這個exception該往哪裡拋呀?內存不夠的時候你想拋出一個 OutOfMemoryException,可是內存已經不夠了,此時完全無能力構造這個異常又該怎麼辦呢?
- 處理器兼容:C++的類依賴基地址+偏移地址的定址方式,很多微處理器只有簡單的給定地址定址,不支持這樣一條語句實現BASE+OFFSET的定址,很多C++代碼編譯出來需要更多的指令來運算地址,導致性能下降很多,得不償失。
- 隱式操作問題:C的特點是簡單直接,每行語句你都能清楚的知道會被翻譯成什麼樣子,系統會嚴格按照你的代碼去執行。而用C++,比如 str1 = str2 + "Hello" + str3; 這樣的語句,沒幾個人真的說得清楚究竟有多少次構造和拷貝,這樣的寫法編寫底層代碼是很不負責任的,底層需要更為精細和嚴格的控制,用C語言控制力更強。
當然,說道這裡很多人又說,「C++本來就是 C的超集,特定的地方你完全可以按照C的寫法來做呀。沒人強迫你構造類或者使用異常呀」,沒錯,按 Linus的說法:「想要用 C++寫出系統級的優秀的可移植和高效的代碼,最終還是會限於使用 C本身提供的功能,而這些功能 C都已經完美提供了,所以系統層使用 C的意義就在於在語言層排除 C++的其他特性的干擾」。
很多人都記得 Linus在 2007年因為有人問 Git為什麼不用 C++開發炮轟過一次C++。事實上2004年 C++如日中天的時候,有人問 Linux內核為何不用 C++開發,他就炮轟過一次了:實際上,我們在1992年就嘗試過在Linux使用 C++了。很噁心,相信我,用C++寫內核是一個 「BLOODY STUPID IDEA」。事實上,C++編譯器不值得信任,1992年時它們更糟糕,而一些基本的事實從沒改變過:
- 整套 C++異常處理系統是 「fundamentally broken」。特別對於編寫內核而言。
- 任何語言或編譯器喜歡在你背後隱藏行為(如內存分配)對於開發內核並不是一個好選擇。
- 任然可以用 C來編寫面向對象代碼(比如文件系統),而不需要用 C++寫出一坨屎來。總得來說,對任何希望用 C++來開發內核的人而言,他們都是在引入更多問題,無法象 C一樣清晰的看到自己到底在寫什麼。
C++粉絲們在C++最火熱的時候試圖將 C++引入系統層開發,但是從來沒有成功過。所以不管是嵌入式,還是操作系統,在靠近硬體底層的開發中,都是清一色的 C代碼,完全沒有 C++的立足之地。
應用層的反思
STL出來後,給人一種 C++可以方便開發應用層邏輯的錯覺。由於很多語言層不嚴密的事情,讓STL來以補丁的方式完成,於是很多以為可以象寫 java一樣寫 C++的初學者落入了一個個的坑中。比如 list.size(),在 Windows下vc的 stl是保存了 list的長度的,size()直接 O(1)返回該變數,而在gcc的 stl中,沒有保存 list長度,size()將搜索所有節點,O(n)的速度返回。
由於語言層不支持字元串,導致 std::string實現十分不統一,你拷貝構造一個字元串,有的實現是引用,才用 copy-on-write的方法引用。有的地方又是 new,有的實現又是用的內存池,有的實現線程安全,有的實現線程不安全,你完全沒法說出同一個語句後面到底做了些什麼(見孟岩的《Linux之父話糙理不糙》)。
再比如說我想使用 hash_map,為了跨平台(當你真正編寫跨平台代碼時,你很難決定目標編譯器和他們的版本,想用也用不了 unordered_map),我很難指出一種唯一聲明 hash_map的方法,為了保證在不同的編譯器下正常的使用 hash_map,你不得不寫成這樣:#ifdef __GNUC__
#ifdef __DEPRECATED
#undef __DEPRECATED
#endif
#include &
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 &
#elif (_MSC_VER &< 1300)
#include &
#ifdef __GNUC__ 如果有更好的跨平台寫法,麻煩告訴我一下,實在是看不下去了。一個基礎容器都讓人用的那麼辛苦,使得很多 C++程序員成天都在思考各種規範,沒時間真正思考下程序設計。 由於語言層要兼容 C,又不肯象 C一樣只做好系統層的工作,導致當 C++涉足應用層時,沒法接管內存管理,沒法支持語言層字元串,沒法實現語言層基礎容器。所以需要藉助一些 stl之類的東西來提供便利,但 stl本身又是充滿各種坑的。且不說內存佔用大,程序體積大等問題,當編譯速度就夠嗆了。所以為什麼 C++下面大家樂意重複造輪子,實現各種基本容器和字元串,導致幾乎每個不同的 C++項目,都有自己特定的字元串實現。就是因為大家踩了坑了,才開始覺得需要自己來控制這些細節。stl的出發點是好的,但是只能簡單小程序裡面隨便用一下,真是大項目用,stl就容易把人帶溝里了,所以很多大點的 C++項目都是自己實現一套類似 STL的東西,這難道不是違背了 stl設計的初衷了么? 語言層的缺失,讓大家為了滿足業務開發的快速迭代的需求,創造了很多很基礎的設計靈巧的基類,來提供類似垃圾回收,引用計數,copy-on-write,delegate,等數不勝數的功能。每個項目都有一系列 BaseObject 之類的基礎類,這樣就引入一個誤區,兩年後你再來看你的代碼,發現某個 BaseObject不滿足需求了,或者你和另外一個項目 merge代碼時,需要合併一些根本屬性。圖形和GUI這些萬年不變的模型還好,應用類開發千變萬化,一旦這些設計靈巧的基類不再適應項目發展時,往往面臨著全面調整的代價。 打開一個個 C++大牛們 blog,很多地方在教你 std::string的原理,需要注意的事項。map的限制,vector的原理,教你如何實現一個 string。這就叫 「心智負擔」,分散你的注意力,這是其他語言里從來見不到的現象。戰士不研究怎麼上前線殺敵,天天在琢磨搶和炮的原理,成天在思考怎麼用槍不會走火,用炮不會炸到自己,這戰還怎麼打? 所以此後幾年,越來越多的人開始反思前兩年C++過熱所帶來的問題,比如高性能網路庫 ZeroMQ作者 Martin Sustrik 的:《為什麼我希望用C而不是C++來實現ZeroMQ》,比如雲風的《雲風的 BLOG: C 的回歸》,比如引起熱議的《Why C++ Is Not "Back"》。
using namespace __gnu_cxx;
typedef hash_map&
#else
using namespace stdext;
typedef hash_map&
#endif
全面被代替
2008年以後,行業競爭越來越激烈,正當大家一邊苦惱如何提高開發效率,一邊掉到C++的各種坑裡的時候,越來越多的應用開發方案湧現出來,他們都能很好的代替 C++。各行各業的開發者逐步相見恨晚的發現了各種更加優秀的方案:需要底層控制追求性能的設計,大家退回到 C;而需要快速迭代的東西大家找到各種動態語言;介於性能和開發速度之間的,有java,知乎上好像很多黑java的,語言是有不足,但是比起C++好很多,沒那麼多坑,真正考慮面向對象,真正讓人把心思放在設計上。所以再黑也不能擋住 java在 tiobe上和 C語言不是第一就是第二的事實,再黑也擋不住 java在雲計算,分散式領域的卓越貢獻。所以2005年以後,C++處在一個全面被代替的過程中:
- 底層系統:進一步回歸 C語言,更強的控制力,更精確的操作。
- 網頁開發:2006年左右,C++和 fastcgi就被一起趕出 web世界了。
- 高性能服務:varnish, nginx, redis 等新的高性能網路伺服器都是純C開發的。
- 分散式應用:2007年左右, C++被java和其他動態語言徹底趕跑。
- 遊戲服務端:2008年後進一步進化為 C 和 腳本,完全看不到胖C++服務端了。
- 並行計算:2010年後,go, scala, erlang;而能方便同go介面的,是 C不是C++。
- 遊戲引擎:沒錯 C++和腳本,但是這年頭越來越多的開源引擎下,引擎類需求越來越少。
- 遊戲邏輯:腳本
- 多媒體:SDL純C,ffmpeg是純 C,webrtc的核心部分(DSP, codec)是純C的。
- 移動開發:早年C++還可以開發下塞班,現在基本被 java + objc + swift 趕跑了。
- 桌面開發:Qt+Script, C#等都能做出漂亮的跨平台界面。且界面腳本化趨勢,不需要C++了。
- 網頁前端:JavaScript, Html5, Flash
- 操作系統:FreeBSD, Open Solaris, Linux, RTOS, Darwin(OS X 底層),都是純 C
- 虛擬技術:qemu / kvm (雲計算的基石)純 C,Xen 純 C
- 資料庫:MySQL (核心純C,外圍工具 C++),SQLite 純 C, PostgreSQL / BDB / unqlite 純C
- 編譯器:C/C++並存,不過編譯器用腳本寫都沒關係,我還在某平台用 java寫的 C/C++編譯器
- 大數據:kafka, hadoop, storm, spark 都使用 Java
- 雲存儲:openstack swift python, hdfs java, 還有好多方案用 go
可以看出,即便 C++的老本行,GUI和圖形(確實也還存在一些短期內 C++無法替代的領域,就像交易統里還有 COBOL一樣),這年頭也面臨的越來越多的挑戰,比如新發布的 Rust (如何看待 Rust 的應用前景? - 知乎用戶的回答)。可以發現,開發技術多元化,用最適合的技術開發最適合的應用是未來的趨勢。而為這些不同的技術編寫高性能的可控的公共組件,並輕鬆的和其他語言介面,正是 C語言的強項。所以不管應用層語言千變萬化,對系統級開發語言C的需求還是那麼的穩定,而這個過程中,哪裡還有 C++的影子呢?
話題總結
所以說未來的趨勢是:C x 各種語言混搭 的趨勢,從TIOBE上 C++的指數十年間下跌了三倍可以看出,未來還會湧現出更多技術來代替各個角落殘存的C++方案,C++的使用情況還會進一步下降。所以題主問學習純C是否有前途,我覺得如果題主能夠左手熟練的掌握 C語言,培養系統化的思維習慣和精確控制內存和硬體的技巧;右手繼續學習各種新興的開發技術,能夠應對各個細分領域的快速開發,碰到新問題時能左右開弓,那麼未來工作上肯定是能上一個大台階的。至於C++ 嘛,有時間看看就行,逼不得已要維護別人代碼的情況下寫兩行即可。
故事分享
古代用弓箭進行遠距離攻擊時,對射手要求較高,瞄準難度大,需要一直使勁保持准心。戰鬥中一個弓箭手開弓二十次就需要比較長的休息時間。弩的威力遠勝於弓,秦弩的製造就如現代的自動步槍一般精密無二,它既可以延長射擊,又可以精確瞄準。弩箭的發射速度更是弓箭的數倍,威力驚人。因為弩的操作非常簡單,不需要射擊技巧,平民很容易掌握它的使用方法。秦國靠著弩兵,在戰爭中取得了不少優勢,被人稱為 「虎狼之師」。
日本投降時,天皇下罪己詔。很多士兵不願意相信這時真的,找種種理由拒絕相信。有的士兵甚至以為天皇的廣播是敵人誘降的把戲,於是躲到叢林里繼續三五成群的收集情報,襲擊可以攻擊的目標,等待上司來給他們下達新命令。直到好幾年後看到周圍的人都穿著日常的便裝了,而來巡山的 「敵人」 也從士兵變為了巡邏隊,他們都還覺得這是敵人的偽裝。而同時,德國戰敗時,最後的黨衛軍一直戰鬥到 1957年才肯投降。
-----------------------------------------很多人覺得 java慢,C++快java 10倍以上已經是上世紀的事情了,現代的 java 只比 C/C++慢 70%,C++連1倍都快不了 java。也不要覺得動態語言慢,javascript只比C/C++慢 2.7倍。luajit只比 C++慢 5.8倍。在 jit技術發展的今天,C++在性能上離動態語言/java的差距越來越小,可易用性和生產效率上的差距,卻和動態語言/java 比起來越來越大。
---------------------------
最後,補充一張圖:
----
去吧,Php是世界上最好的語言,C語言第二,C++第三。
正經答題:
你的工資高低跟你學什麼編程語言沒有一毛錢的關係,而是和你從事的行業直接相關。計算機科學中的演算法、數據結構、邏輯等等方面和你用的編程語言並無關聯。武俠小說中的高手,飛花落葉皆可傷人。當你從事編程一兩年之後就會明白這個道理的。
另:任何涉及到計算機語言的討論都會立刻變成宗教戰爭,這個問題就是實例。如果家裡不是特別窮,還是不要因為短期的現金流選擇一份工作。
我是做unix kernel的,就是所謂的純c開發。c語言確實本身沒有各種library但對於成熟的操作系統來說,其實linkedlist hashmap都有現成的庫函數讓你使用,無非是使用起來未必像java c++標準庫那麼方便。
錢景還是有的,但市場上做底層的就那麼多,就操作系統而言我覺得現在的發展已經比較緩慢了,更多的創新都是在應用層,所以純c程序員跳槽的選擇要少於java c++。此外,底層確實比app層要難很多,我工作四年很多東西也還是一知半解,而且我也不認為我再干10年就能都明白,這也是為什麼我最近在積極面試...當然如果你對底層特別有熱情另當別論。如果是精通或熟悉了C++等高級語言,再以純C來進行合適的工作,有前途;
如果是因為畏難而放棄C++等高級語言,僅會C所以用純C來進行工作,前途不明朗。
嵌入式的工作環境堪比工地,選擇請慎重!!
BOOL CreateProcess
(
LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATIONlpProcessInformation
);
拿好
———————————
雖然如此,直接接觸底層寫起來還是很爽的
怎麼會有所謂純C程序員。
碼農掌握的語言怎麼也得有3到4種吧。就我的經驗,C寫driver或kernel module,C++搞OpenCV,Python用來快速prorotype,Java庫多不想自己寫庫的時候可以直接用Java的。而且這些語言都是在同一個項目里用到的。
還沒見過誰做個小玩意還只用C,工作更不用說了
而且C或C++掌握好了,新學Java Go C#順得一筆
我來告訴你吧,我是本科畢業做了一年java,然後去讀研,然後工作從事c的網路開發,再去了一個創業公司做大數據java,現在在一個新的公司負責從中間件,web伺服器,緩存,資料庫,消息隊列的掌握和線上難題攻關。讓我們來看看c和java在比較火的互聯網行業里有哪些用武之地
1各種中間件,比如單點故障的keepalive,負載均衡的haproxy都是用c寫的
2 靜態伺服器nginx是c寫的
3動態伺服器tomcat,jetty,resin,play都是java
3.1網路框架netty,mina是java
4 緩存,比較火的redis,c語言
5 資料庫mysql,c語言
6 消息隊列比如kafka,kafka可以認為是java的領域
7 文件緩存varnish用的c
…………………………我是分割線
再來看看大數據
hadoop,storm,spark簡直就是java包打天下。
總結:純粹討論語言的前途意義不大,目前java和c牢牢佔據兵器譜狀元和榜眼之位。如果有機會實現在同一個公司輪崗,c和java全通,對你後面完成架構師所需要的組件的快速掌握非常有幫助,我之前做了2年的c讓我深刻理解了tcp/ip協議,然後看到各種網路程序理解起來分分鐘的事情。
最後再說一句:很多做java的人壓根不知道什麼是網路
--------------
題主提到創始人有矽谷背景,正好我參加的上家公司也是這樣的創業公司,說起來幾個創始人有什麼伯克利之流名校背景,但是仍然暴露出來很多問題,比如他們的技術是否足夠過硬?拿到的是碩士學位還是博士學位?管理是否OK,千萬不要被那些虛的給蒙蔽住,我就是覺得上家公司的技術和管理糟透了才離開的。
只要能找到有錢景的工作,那麼學任何一種語言就有錢景了。所以問題不是學C有沒有錢景,而是你學某種語言和技術時,它有多少機會讓你找到有錢景的工作。這其實不涉及到語言與技術的優劣之分,只是一種各技術充分競爭下的市場選擇。
另外,再說些題外話,依據你要做的事去選擇你最順手的工具。比如我寫自己的個人網站,我的選擇是C#而不是Java,為什麼呢?原因很簡單:因為我非常熟悉C#,開發效率比Java高得多,那我就用C#了,節約時間成本啊!確實,Java在Web開發領域的佔有率比C#高很多,但這關我P事?
當然有前景,而且很多地方的C語言程序難度都很大,譬如搞嵌入式的。之前有聽說個新聞,不知道豐田是不是用的C語言來寫汽車的控制系統,說是他們的程序只有一萬五千個全局變數,暫時還沒遇到什麼維護的問題。
NVIDIA 上海常年招 C/C++ 工程師
站內私信
你們這些娃老是黑 C++,我們現在都招不到 C++ 工程師了
"純C語言開發存儲器操作系統的offer",做這樣的工作你還在問某個語言是否有前景,說明你沒理解軟體開發工作真正重要的是基礎知識,而不是語言。
你要把「存儲器操作系統」完全弄懂了,不會 Java 也能找到工作...@韋易笑和 @GWB NMCF兩人的演出簡直精彩。雖然兩個都是黑C++的,還是不忘拆一下彼此的台。
C 沒有 namespace,沒有泛型,沒有 vector,沒有 map,沒有 string,沒有 interface,沒有 unique_ptr,沒有 RAII
什麼都得自己做,什麼都得提心弔膽的,生怕一不小心就野指針了
祝你好運
推薦閱讀:
※有哪些能規劃旅行路線的 App?
※一個人如何開發一款 App?
※作為計算機專業學生,最應該學習的課程前五位是什麼?
※有哪些軟體相關的公司,開發流程比較規範?
※想成為計算機技術高手,一定要懂彙編嗎?