標籤:

為什麼 C++ 能夠源碼級兼容C語言?

問題1:為什麼C++ 能夠 源碼級兼容C語言?

是編譯器內部實現C語言編譯器的所有特徵嗎?

問題2(引申問題):除了C++還有什麼語言能夠源碼級兼容C語言?

2016-01-07 更新 補充

感謝大家回答。

何必那麼較真 100% 兼容呢,源碼大部分兼容不能算嗎?典型 vc++編譯器可以編譯C語言程序。

再者

oc 蘋果的想法很美好。但是oc 僅限於蘋果自家平台吧。


問題1:為什麼C++ 能夠 源碼級兼容C語言?

是編譯器內部實現C語言編譯器的所有特徵嗎?

這是從C++設計的時候就做出來的選擇。

我有幾次做技術分享的時候都被問道過一個問題,那就是C++為什麼要選擇兼容C?而我的回答則是若不兼容C,或許現在已經沒有C++了,不能忘記歷史。若回顧C++的成功,這一個選擇也無疑是明智的。C++之父Bjarne在The Design and Evolution of C++書籍中曾提到過選擇C的四個理由:Flexible, Efficient, Available,Portable。Flexible是指C語言本身並沒有什麼內在限制,你幾乎可以把C應用於任何一個領域。Efficient是大家都知道的,因為C語言足夠貼近底層,幾乎是直接反映了計算機的基本概念。Available是指無論是嵌入式,還是大型機,都能找到一個可靠的C編譯器以及標準庫,這是很大的定心丸。Portable則是指C語言的代碼很容易遷移,若是使用標準C,無論是從一個操作系統到另外一個操作系統(如Windows到Linux),還是一個體系架構到另外一個體系架構(如Power到x86),雖然說不能說非常順利,但是這樣的代價是完全可以接受的。

於是,正是因為這些優點,讓Bjarne決定讓C++從C這個基點開始,來設計一個Better C。而為了充分的保留C的優點,Bjarne選擇了讓C++從源代碼級別兼容C,並且對編寫C出現的一些主要問題進行了矯正,這主要是類型系統上面,所以,C++在源代碼級別是幾乎完全兼容的。選擇了源代碼級別兼容C,那麼付出的一個代價則是讓語言和編譯器都變得複雜,然而在最初設計C++的時候,Bjarne認為這是可以接受的,包括最開始的C++編譯器CFront也是把C++轉為C。

而再回顧C++的設計,它其實帶著有兩個目的。一個是可以提供程序員一種載體,以便他們可以描述他們需要執行的行為。而另外一個目的則是可以為程序員提供一組概念(Concepts),以便可以幫助他們思考如何利用語言提供的東西來解決問題。第一個目的則要求語言足夠接近底層,可以簡單高效的完成,而C在這裡也的確是一個很好的選擇。而第二個目的,也是C++主要在C的基礎上添加的,也是C++進化的時候主要添加的東西。在C++的進化中,Bjarne思考了很多語言,如Ada,Modula-2, Smalltalk,Simula,Clu等,而C++也的確受到了很多語言的影響。這些語言或許在我們這一代中的程序員中都已經很少直接用到,甚至都很少聽到了,然而這些語言卻對C++有著重要的影響,如Ada為C++提供了namespace,template, exception等靈感,包括Clu, ML也在exception的構造中扮演了重要的角色。而這些老一輩的語言不僅影響著C++這樣有一些「老」的語言,若讀The Go Programming Language,我們也會發現這些老語言也對Go這樣的新語言有著重要的影響,如Modula-2,Oberon,Oberon-2等。

最後,C++選擇C還有一個理由,則是Bjarne當時工作在Bell實驗室,在那裡有著Ken Thompson, Dennis Ritchie, Brian Kernighan,Steve Johnson等人。若C++選擇了C,那就意味著有C語言之父和很多大牛可以直接提供指導與反饋,這樣的資源必然要利用起來。有了大牛的滋養,加上C++出身名門——Bell實驗室,也對C++的成功有了一定的幫助。出身名門不僅對人很重要,其實對於程序語言也是如此。記得有人問過我對Go,Rust,D等語言的看法,當我說到Rust的時候,我就在想,若是Rust可以出身一個更有錢的爹,或許會更順利一些。

再次回到題主的問題,是編譯器內部實現C語言編譯器的所有特徵嗎?不同的編譯器會有不同的處理方式,一些編譯器(如Clang)是一個前端,一些共同的地方採用共同的組件,不同的地方單獨處理。然而有一些編譯器則是不同的前端,C和C++是分開的。

除了C++還有什麼語言能夠源碼級兼容C語言?

不嚴格的說,Objective-C算。


C++ 並不是在源代碼級別兼容 C,它只不過是語法和 C 大部分類似而已。很多合法的 C code 並不能通過 C++ 編譯,反之也是不行。

實際工程里的 compiler,比如提問者提到的 Visual C++ 的 compiler,裡面既有 C 的 parser 也有 C++ 的 front end。在項目里 C 的代碼一般是用 .c 存儲,C++ 用 .cpp。編譯器會根據擴展名使用相應的 parser。直接把 C code 拷入 .cpp 文件,能通過編譯的往往僅限於純數學運算的代碼。你說不要「較真 100% 兼容」,那還是有那麼一點點牽強,因為有些 Java code 你 copy 到 .cpp 里也幾乎能編譯通過呢。

C 和 C++ 能在源代碼級別混用主要是它們在 struct 和 function signature 方面詳細規定了互操作的協議。這只是語法里的一小部分做到了有限兼容,而且還要藉助 extern "C" 這種 special handling 的幫助。從這點來說,C 和 C++ 的互操作能力比 Pascal 和 C 強點有限。

從源代碼混用來說,Objective-C 的 parser 做得更好。你可以說它是一個 parser 兼容兩種語法。或者說它是兩個 parser 但是可以在 sub-file 級別做模式切換。無論怎麼看都比 C++ 做的好。至於提問者說的「oc 蘋果的想法很美好。但是oc 僅限於蘋果自家平台吧」—— 第一,這不僅僅是一個「想法」,而是上萬工程師每天都在用的成功實踐。第二,任何複雜的開發其實都是綁定的在一個平台上,只有一小部分 core component 可以事先考慮跨平台性,所以「僅限於……自家平台」做為一個 consideration 在很多情況下屬於「too soon to worry about too much」,第三,「僅限於……自家平台」對這個語法級別的問題意義不大。

補充:認為 C++ 真的兼容 C 的,不妨問問自己或者身邊的老手有沒有寫過下面的代碼:

#if __cplusplus
define EXTERN extern "C"
#else
define EXTERN
#endif


肯定會有人說不問是不是,就問為什麼...

不嚴格考量每一個特性的話可以說大部分兼容。

下面是回答:

1.兼容特性大部分是的。

2.不太嚴格的話OC應該也算


為什麼 C 語言中的一些特性不被 C++ 支持? - 陳碩的回答

再貼個我書上寫的。


注: 之前的回答把ABI層面的兼容和FFI跨語言調用的概念弄混了, 謝謝@Leedy指正!

問題1:為什麼C++ 能夠 源碼級兼容C語言?

歷史原因: C++設計之初就是以兼容C語言為目標的, 所以能夠兼容.

邏輯原理: C++作為C的超集(大部分時候), 自然是可以兼容的. 想像你只是選取部分的C語言功能重新命名為`C--`語言, 那麼C就是可以兼容`C--`語言的.

技術原理:

編譯器的本質就是對源代碼進行語法和語義的分析, 然後生成二進位文件. C++編譯器設計之初就考慮到了C的語法和語義, 所以能提供源碼級支持.

問題2(引申問題):除了C++還有什麼語言能夠源碼級兼容C語言?

感覺大部分對C做拓展的語言都能源碼級支持C吧(純個人感覺).

注1: 強力推薦一本大作, 以前星爺在電影里推薦過的!

《程序員的自我修養 - 鏈接、裝載與庫》

注2: 了解一下FFI和ABI兩個概念, 應該能拓展一下思路.


我個人的感受是,C和C++越來越像兩種語言了。兩者分歧多於共性。


雖然問題中的前置條件在大部分情況下,是正確的,但是我還是想用個例來否定。

C99 中的 feature :

designated initializers [1]

int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };

/////
struct Point {
int x, y;
};

struct Point p[3] =
{
[2].y=6, [2].x=5,
[1].y=4, [1].x=3,
[0].y=2, [0].x=1
};

struct point q[10] =
{
[0 ... 4].x = 1,
[5 ... 9].y = -1
};

/////
struct a {
struct b {
int c;
int d;
} e;
float f;
} g = {.e.c = 3 };

/////
struct node {
char *value;
struct node *next;
};

struct node head = {
.value = "make a",
.next = ((struct node) {
.value = "BIG NEWS",
.next = NULL
})
};

這些代碼都能通過 C99 ( GCC,其他的不知道) ,你用C++ 的編譯器試試。

關於C與C++兼容性 請參考 Compatibility of C and C++

問題1:為什麼C++ 能夠 源碼級兼容C語言?

是編譯器內部實現C語言編譯器的所有特徵嗎?

編譯器只負責語言實現 , C++ 為什麼兼容 C 是 C++ 設計者的決策 。

至於為什麼 C++ 大部分兼容 C,藍色大大的回答是正解。

最後 Objective-C 兼容 C ,

Objective-C 不是僅限於 Apple 平台,Objective-C 只是小眾 , 除了 Apple 就沒什麼人用罷了。[2]

Besides the GCC/NeXT/Apple implementation, which added several extensions to the original Stepstone implementation, another free, open-source Objective-C implementation called the Portable Object Compiler

[39]

also exists. The set of extensions implemented by the Portable Object Compiler differs from the GCC/NeXT/Apple implementation; in particular, it includes Smalltalk-like blocks for Objective-C, while it lacks protocols and categories, two features used extensively in OpenStep and its derivatives and relatives. Overall, POC represents an older, pre-NeXT stage in the language"s evolution, roughly conformant to Brad Cox"s 1991 book.

It also includes a runtime library called ObjectPak, which is based on Cox"s original ICPak101 library (which in turn derives from the Smalltalk-80 class library), and is quite radically different from the OpenStep FoundationKit.

---------------------------

[1] C99

[2] Objective-C


哈哈! 問得好~

C++ 真的 對 C全兼容么? 不盡然,不是兼容所有C語法,我這裡說下我的小小看法,參考參考

C++設計者 就想兼容C,就是這個原因, 他設計編譯器 就是仿照C的介面去設計的,所以類似於g++,clang 這樣的編譯器兼容C。你如果設計一門語言,也可以兼容C啊;也可以兼容 50%java,50%C都可以,只要你喜歡。中間是否有部分直接拿過來用,不得而知啊。

還有什麼語言兼容C? Objective-c 語言, 在xcode編譯器中, 也兼容大部分C

我水平只能談到這裡了


推薦閱讀:

C中int main()和int main(int argc,char* argv[])的區別?
C primer plus該怎麼看?
新手使用c primer plus中文第五版學習c語言,windows下推薦用什麼編譯器?
如何看c primer plus這本書?
Qt C++ 如何實現自我反射?

TAG:C編程語言 | C |