C是中餐廚師的菜刀,做啥菜就那一把刀,切菜切肉切魚,都是這一把刀,刀工好的師傅,豆腐都能切成一朵花。無論你提什麼概念,都能用指針給你做出來,如果不行,那就用指向函數的指針,指針的指針,指向函數指針的指針。。。。
C++就是西餐廚師的刀,有一大堆不同款式的刀,切不同的東西得用不同的刀,每種刀還有不同的手法,顯得非常專業,高大上。
中廚刀,簡單,但深入高階難,難在複雜使用技巧,做啥都是這一把刀,要切出花來,刀工需要練的,一般人練不好。
西廚刀,複雜,但是使用難度相對低,需要掌握一堆刀的功能限制。但刀太多,功能干涉太多,沒準啥時候沒喫透就踩坑了。真正喫透也很難。
西餐廚師離開這些功能複雜的西廚刀,就會顯得手忙腳亂,如果只有一把中廚刀,甚至不會做菜了。
中餐廚師用這堆西廚刀,會不耐煩,最後還是挑出一把最順手的,當成中廚刀用,其他的閒置。
西餐廚師經常炫技方式就是這刀我會用,那刀我也會用,組合起來還會用。一大堆使用西廚刀的術語名詞和隱藏小技巧。
中餐廚師炫技方式就是,隨便你提啥需求,我都是用這一把刀給你切出來,刀工還強。
西餐廚師看不起中餐廚師,就一把刀,太簡陋,沒逼格。
中餐廚師看不起西餐廚師,一大堆刀,也沒見菜更好喫,而且那一堆西廚刀的功能,咱就一把中廚刀也能切出來。
是的,C++所有新特性,用C都能做出來,無論是面向對象還是函數式編程還是元編程。所以,不要再說C++是面向對象的,而C是面向過程的,這不是本質區別。但C腦補編譯器確實也不是輕鬆的活。
初級階段,C比C++容易學,畢竟語法簡單,關鍵詞少。
中級階段,C++更容易更強大。畢竟有強大的編譯器支持,只要掌握這些語言特性,就已能實現強大的高級功能。而C還需要腦補編譯器,才能實現面向對象等高級特性,不是每個人都能做到,大學課程也不教這些。
高級階段,C++可能變成語言發燒友,各種特性組合會成爲泥潭,牽扯極大的精力。而用C度過中階段後,更深入理解計算機和程序的哲學本質後,會有一種無所不能的感覺。C反而是束縛更少,更自由,更高效的工具。
一個C++高手,能準確掌握更多更復雜的高級語言特性組合,高效率響應業務需求,快速迭代,代碼優雅簡潔,魯棒性好,維護性好,擴展性好。
一個C高手,能掌握更多的基礎模塊實現方案,什麼無鎖消息隊列,內存管理,線程調度器,時鐘,各種算法庫,甚至不同風格的面向對象的架構,這都是自己純手工打造,然後根據業務需要定製這些基礎模塊的設計方案和參數,以追求應用業務的極致性能,和極致可靠。
C高手往往不太喜歡C++那一套,因爲很多東西不能自己掌控。這讓習慣掌控一切的C程序員覺得腳下有些發虛。
C++高手往往也不太喜歡C,因爲很多輪子要自己造。讓習慣快速響應迭代的C++程序員無比煩躁。
都是圖靈完備的語言。C能做到的,C++肯定能做,畢竟C++是C超集。而C++能做到的,其實C也能做到,只需要腦補一種編譯範式而已。
如果非要在哲學上說C和C++有什麼區別,那麼C是心法派,C++是語法派。
每當有新概念新範式出現,C++標準組織就會開發新特性新語法,以提供這種新範式。
而C則腦補一種新的心法(數據結構和算法)來解決,在語法層面儘量少增加特性,幾乎很少變化。
C和C++又有點像武俠之氣宗和劍宗
入門是氣宗C簡單,入門要學的東西少。而劍宗C++不僅要學氣宗的C,還需要學劍宗的這些++,入門就複雜一些。
修煉進展,是劍宗C++來的快,畢竟有一大堆現成的語法範式,不需要知其所以然,只需會用,就能發揮劍宗招式的威力。而氣宗C還要掌握一大堆基礎數據結構和算法以及設計範式,研究精深,知其所以然,才能真正發揮威力。
上限,是氣宗C來的高。等真正深入到高階編程,會發現每一種現成的語法範式和庫,某種意義上,便捷的另一面就是束縛。語言編譯器做的工作越多,庫越強大,編程束縛反而越大;而語法越少編譯器越簡單,反而自由度越高而且越穩定可靠,可供發揮的上限也越高。
對於以C爲主的高水平團隊,C現有的語法不是太少,而是多了,反而還要設定一些編程規範加以限制。所以一些真正經典優美的C代碼,往往都是樸實無華的,很少在語句技巧層面炫技。
以C++爲主的高水平團隊,也常常制定編程規範,對語法使用加以限制,限制可能比C更多。
一個團隊水平高低,從其編程規範就可見一斑。水平越高,往往規矩越多。
當然,真正的高手,都是氣劍雙修的,在語法層面幾乎都是樸實無華,從不炫技,人家炫的是思想。
有人想聽Python是什麼刀。
嗯,竊以爲,Python更多像速凍食品。
速凍食品能快速的滿足需求填飽肚子,而不是餓着肚子還需要洗切烹飪,在底層原料處理環節消耗大量的時間精力。
Python最大優勢就是用起來方便。不是每個人都需要懂編譯器實現,各種算法的細節,各種指針的奇技淫巧。大部分人需要的只是快速方便的解決現實問題。
所以,與其說Python兼容面向對象和面向過程,不如說Python是面向問題的。
Python的編譯器,和大量的庫,都是用C/C++寫的,會熟練使用這些庫,也就站在了巨人的肩膀上,還不是一個,是一羣巨人。掌握這些,足以快速的解決多數問題。
那麼速凍食品就沒有逼格,手工現做就有逼格?其實也不是,一切從現實需求出發,能最快最好滿足需求的工具,就是最好的工具。
Python高手,會掌握大量的庫和設計範式,信手拈來,快速滿足需求。
而進階Python高手,還會自己用C來做庫,以在某些特殊場景下,突破開源庫的功能和規格束縛。
又有朋友問,JAVA,C#,VB,VBA是什麼刀?
這真當咱是刀匠嗎?還是鐵匠? 嗯 ? ~ o( ̄▽ ̄)o
好吧,所有的刀款式,這回一次性解決。
所有編程語言,本質上都是工具。
所有刀,本質上也是工具。
都是工具,工具間,自然有類似特徵,會有些相通之處。
理解這些有趣的相通之處,有利於我們快速的掌握一種新工具。而不是迷失在新工具的細節之中。
而這些有趣的相通之處,其實並不是孤立零散的。
掌握這些有趣相通之處的分佈規律,可以更深刻的理解這些相通之處。
然後,對新工具理解,就是二次方的深刻度。
就像練武,學會心法,招式訓練效果倍增。
而學會心法的心法,功力提升速度則加速到二次方。
二次方程,需要一個座標軸。
建立座標軸,首先需要一個零點,然後需要一個無窮遠。
從零點到無窮遠,就是一個數軸。
當你內心建立起這樣一個數軸,所謂心法的心法,就水落石出,一目瞭然,不需要別人告訴你特徵,打比方解釋給你聽,扯什麼中式菜刀和西式廚刀的故事。
你自己就可以發現規律。
你自己就可以打無數的比方,信手拈來。
那麼,編程語言的零點,在哪裏?
圖靈機。
是的,圖靈機,是近幾十年來一切計算機技術的起點。
那麼,無窮遠,又在哪裏?
宇宙間萬事萬物的無限複雜度,不正是無窮遠嗎?
當我們從圖靈機出發,去解決宇宙間萬事萬物的無限複雜的過程,就是從零點到無窮遠的過程,就產生了數軸。
一旦有了數軸,所有的芯片架構和編程語言,都可以在這數軸上有一個位置,也就是座標。
當你俯瞰這些座標構成的散點圖,哦,原來如此,不過如此,就像魔術師的技巧被解密了。
讓我們出發。
圖靈機是零點,第一個點在哪裏?
圖靈機是數學理論上的抽象模型,而馮諾依曼架構個是可落地的工程計算架構。
實現馮諾依曼架構,需要一套指令集、一些指令集配套的寄存器、運算單元、地址總線、數據總線、內存等。然後,就可以開始機器碼的編程。
基於CPU指令集的機器碼編程,可比基於圖靈機的機器碼編程來的高效的多。
但,每一步效率的提升,都是拿自由兌換的。
指令集也不例外,有位寬的限制,有指令位寬的區別,有寄存器的區別,有精簡指令集複雜指令集區別,等等,等等。
指令集,正是編程遇到的第一次束縛。
所以,從馮諾依曼架構開始出發,有各種各樣的指令集。試圖用不同的實現折中,來換取不同的效率優化。
機器碼編程太累,就有了彙編。彙編跟機器碼幾乎是一一映射,無損壓縮。
彙編還是累,就有了一些初步的高級語言,如廣泛應用成熟的C。
C提供了函數,方便了程序設計,但卻剝奪了CPU寄存器的可見性,戴上了棧空間的束縛,等等。
C++提供了面向對象的語法便捷,但面向對象卻限制了指令交叉訪問數據的自由和效率。
Java等語言提供了內存管理便捷,但剝奪了程序自主內存管理的自由和效率。
面向宇宙萬物的無限複雜度,每一步編程效率的提升,都是拿自由兌換的,毫無例外。
當我們想要更大的便捷性和功能,就面向具體問題,以可以忍受的些許自由代價,來換取解決具體問題的範式,以此獲得效率的提升,也就是更高級的語言。
當我們想要更大的自由度,就向零點回退。
踩着前人的腳步,熟悉每一步自由換取便捷的手法,你心中就有了數軸。
有了數軸,你就可以俯瞰所有的語言、程序、和架構設計。
熟悉這一切,你甚至可以根據需要創造新的編程語言,新的設計範式。
就是這樣而已,沒什麼魔法。
本文完。
課後作業:
圖靈機真的是零點嗎?
這個軸的負數方向意味着什麼?