C與C 的區別與相互呼叫

2021-07-04 04:54:33 字數 4851 閱讀 2979

一:兩者的區別

從語言本身的角度:全面相容c語言;支援物件導向程式設計;c++的可重用性、可擴充性以及可維護性較好。是乙個結構化語言,它的重點在於演算法和資料結構。c程式的設計首要考慮的是如何通過乙個過程,對輸入(或環境條件)進行運算處理得到輸出(或實現過程(事務)控制)。c++,首要考慮的是如何構造乙個物件模型,讓這個模型能夠契合與之對應的問題域,這樣就可以通過獲取物件的狀態資訊得到輸出或實現過程(事務)控制。 所以c與c++的最大區別在於它們的用於解決問題的思想方法不一樣。之所以說c++比c更先進,是因為「 設計這個概念已經被融入到c++之中 」

從語言的結構:在編寫c語言程式的時候,程式的結構主要包括預處理程式、自定義型別說明、常量定義、函式定義以及主函式定義幾大部分;在編寫c++語言程式的時候,從物件導向的角度,程式的結構主要包括類的定義和使用兩個主要組成部分。

從處理輸入輸出的角度:c語言中使用scanf()函式實現格式化輸入,使用printf()函式實現格式化輸出。如果輸入和輸出函式中格式化型別與實際型別不符時,c編譯器無法檢查出錯誤,但是程式執行時會出現問題。而

c++採用了流的形式來控制輸入和輸出操作,cin為標準輸入流,cout為標準輸出流;它們都為對物件來使用,正是一切皆物件的理念。即使輸入輸出語句中定義了不同型別的資料,在編譯和執行過程中將不會出現任何錯誤資訊。

從區域性變數的宣告方式看:在c語言中,全域性變數必須宣告在所有函式之前,區域性變數在函式的內部必須宣告在所有可執行語句之前;

c++中允許在**模組中的任意位置對區域性變數進行宣告。

從函式過載的角度:c語言中不存在函式過載的概念,不允許出現名稱相同的函式;

c++允許過載函式,即對於函式引數型別不同、引數個數不同或者引數型別和個數都不同的情況。

從處理動態儲存分配角度:c語言中使用malloc()函式分配動態記憶體空間,使用free()函式釋放動態記憶體空間;這僅僅是用於分配記憶體空間。由於malloc函式返回的是void型指標,因而需要強制轉換型別。

c++則採用new和delete操作符,new可以自動計算所要分配的記憶體大小,並返回正確的指標型別;除了分配儲存空間之外,new 自動呼叫建構函式。

強制型別轉換角度:c語言必須將型別括起來,c++可以將變數括起來。比如int(a)在c++中是正確的,但是在c語言中是錯誤的,必須寫為(int)a。

從定義結構體的角度:在c中宣告struct變數要這麼寫:struct mystruct a;  在c++中前面不用加struct:mystruct a; 此外,在c++中,struct結構體支援成員函式的定義,c中不行。另外要注意的是,c++中成員函式的預設訪問說明符為public,這一點和類不同,類的預設訪問說明符為private.

bool型別的角度:c++中有bool(或boolean型別);c中可沒有這樣的bool型別,均為數值型別!需要注意的是真為非零,假的數值為0。

賦值語言的角度:c語言中的賦值只有一中即:=;  c++中除了使用=外,還可以使用()。例如:int  x(5);就等於: int x=5; 我想這種寫法是給c++中物件初始化時為了對基類的屬性以及常量來進行賦值。

運算子&的角度:&運算子最基本的含義是取位址,c和c++中都支援這一語法。但在c++中&還可以表示引用。有了引用的概念後函式呼叫可以作為左值。

const的角度:在c++的類函式中,函式可以聲名是可以用const,表示這個函式沒有改變類中的任何屬性。而在c中,不能有這樣的生明。

extern的角度:在c語言的某些版本中,可以在程式中多次使用乙個全域性變數而無需使用extern說明符。但在c++中除定義全域性變數外,在其他模組使用應先用extern生明。

從void指標的角度:在c語言中void指標可以賦給任何型別的指標,但在c++中,卻不行,但可以先進行強制資料型別轉換,再進行賦值。

從stl的角度:標準c++擁有強大的標準容器類,對很多問題管理更加方便些。

異常處理的角度:c++能夠對異常進行處理,而不僅僅像c語言那樣去報告乙個問題。

從運算子過載的角度:c++支援運算子過載,這樣在設計程式的思想更加符合解決現實的世界問題的思路。

從內聯函式的角度:為了解決函式在呼叫過程中產生的棧開銷,c++支援內聯函式。

二:兩者之間的相互呼叫

如果c++程式要呼叫已經編譯好的c函式,如何呼叫:假設某個c函式的宣告void foo (int x, int y); 該函式被c編譯器編譯後在庫中的名字為_foo,而c++編譯器則會產生像_foo_int_int之類的名字用來支援函式過載和型別安全連線。由於編譯後的名字不同,c++程式不能直接呼叫c函式。c++提供了乙個c連線交換指定符號 extern 「c」來解決這個問題。extern「c」 或者extern「c」。這就告訴c++編譯譯器,函式foo是個c連線,應該到庫中找名字_foo而不是找_foo_int_int。另外說明一點:c++編譯器開發商已經對c標準庫的標頭檔案作了extern「c」處理,所以我們可以用#include在c++程式中直接引用這些標頭檔案。

如何理解 extern"c":extern"c"包含雙重含義,從字面上即可得到:首先,被它修飾的目標是「extern」 的;其次,被它修飾的目標是「c」的。讓我們來詳細解讀這兩重含義。被extern"c"限定的函式或變數是extern型別的;extern是c/c++語言中表明函式和全域性變數作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其宣告的函式和變數可以在本模組或其它模組中使用。記住,下列語句:extern int a; 僅僅是乙個變數的宣告,其並不是在定義變數a,並未為a分配記憶體空間。變數a在所有模組中作為一種全域性變數只能被定義一次,否則會出現連線錯誤。通常,在模組的標頭檔案中對本模組提供給其它模組引用的函式和全域性變數以關鍵字extern宣告。例如,如果模組b欲引用該模組a中定義的全域性變數和函式時只需包含模組a的標頭檔案即可。這樣,模組b中呼叫模組a中的函式時,在編譯階段,模組b雖然找不到該函式,但是並不會報錯;它會在連線階段中從模組a編譯生成的目標**中找到此函式。與extern對應的關鍵字是static,被它修飾的全域性變數和函式只能在本模組中使用。因此,乙個函式或變數只可能被本模組使用時,其不可能被extern「c」修飾。被extern"c"修飾的變數和函式是按照c語言方式編譯和連線的;未加extern「c」宣告時的編譯方式,首先看看c++編譯器中對類似c的函式是怎樣編譯的。首先看看c++編譯器中對類似c的函式是怎樣編譯的。作為一種物件導向的語言,c++支援函式過載,而過程式語言c則不支援。函式被c++編譯後在符號庫中的名字與c語言的不同。例如,假設某個函式的原型為:void foo (int x,int y); 該函式被c編譯器編譯後在符號庫中的名字為_foo,而c++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都採用了相同的機制,生成的新名字稱為「mangled name」。_foo_int_int這樣的名字包含了函式名、函式引數數量及型別資訊,c++就是靠這種機制來實現函式過載的。例如,在c++中,函式voidfoo(intx,inty)與voidfoo(intx,floaty)編譯生成的符號是不相同的,後者為_foo_int_float。同樣地,c++中的變數除支援區域性變數外,還支援類成員變數和全域性變數。使用者所編寫程式的類成員變數可能與全域性變數同名,我們以"."來區分。而本質上,編譯器在進行編譯時,與函式的處理相似,也為類中的變數取了乙個獨一無二的名字,這個名字與使用者程式中同名的全域性變數名字不同。所以,可以用一句話概括extern「c」這個宣告的真實目的。實現c++與c及其它語言的混合程式設計。

extern "c"的慣用法:在c語言的標頭檔案中,對其外部函式只能指定為extern型別,c語言中不支援extern "c"宣告,在.c檔案中包含了extern"c"時會出現編譯語法錯誤。因此,我們經常會做如下處理:

#ifdef _cplusplus

#define general_extern extern「c」

#elseif

#define general_extern extern

#endif

在使用的時候,general_extern int foo (int x, int y) 代替extern "c" int foo (int x, int y); 說明:使用條件編譯,可以有選擇題告訴編譯器,採用哪種方式編譯。如果使用的是c++編譯器,那麼採用extern「c」(實現混合程式設計);如果使用的是c編譯器,那麼採用extern(編譯不會出錯)。

c語言應用c++:在c中引用c++語言中的函式和變數時,c++的標頭檔案需新增extern"c",但是在c語言中不能直接引用宣告了extern"c"的該標頭檔案,應該僅將c檔案中將c++中定義的extern"c"函式宣告為extern型別。

如何實現c呼叫c++介面庫:c一般不能直接呼叫c++函式庫,需要將c++庫封裝成c介面後,才可以使用c呼叫之。所以要了解c封裝c++介面策略。

對由__cplusplus和extern "c"組成的c、c++編譯器編譯標準c函式的通用寫法的理解:由於c++編譯器需要支援函式的過載,會改變函式的名稱,因此dll的匯出函式通常是標準c定義的。這就使得c和c++的互相呼叫變得很常見。但是有時可能又會直接用c來呼叫,不想重新寫**,讓標準c編寫的dll函式定義在c和c++編譯器下都能編譯通過,通常會使用以下的格式:(這個格式在很多成熟的**中很常見

#ifdefined (__cplusplus)

extern"c"

#endif

C與C 之間相互呼叫

c與c 之間相互呼叫 1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由...

C與C 之間相互呼叫

1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由c和c 模組使用。以下...

C與C 之間相互呼叫

1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由c和c 模組使用。以下...