欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++和C的混合編譯的項(xiàng)目實(shí)踐

 更新時(shí)間:2022年06月10日 11:07:32   作者:iheal  
本文主要介紹了C++和C的混合編譯的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

簡(jiǎn)介

C++ 語言的創(chuàng)建初衷是 “a better C”,但是這并不意味著 C++ 中類似 C 語言的全局變量和函數(shù)所采用的編譯和連接方式與 C 語言完全相同。作為一種欲與 C 兼容的語言, C++ 保留了一部分過程式語言的特點(diǎn)(被世人稱為"不徹底地面向?qū)ο?quot;),因而它可以定義不屬于任何類的全局變量和函數(shù)。但是, C++ 畢竟是一種面向?qū)ο蟮某绦蛟O(shè)計(jì)語言,為了支持函數(shù)的重載, C++ 對(duì)全局函數(shù)的處理方式與 C 有明顯的不同。

本文將介紹如何通過 extern “C” 關(guān)鍵字在 C++ 中支持 C 語言 和 在C語言中如何支持 C++。

某企業(yè)曾經(jīng)給出如下的一道面試題

為什么標(biāo)準(zhǔn)頭文件都有類似以下的結(jié)構(gòu)?

//head.h
#ifndef HEAD_H
#define HEAD_H

#ifdef __cplusplus
extern "C" {
#endif

    /*...*/

#ifdef __cplusplus
}
#endif

#endif /* HEAd_H */

問題分析

  • 這個(gè)頭文件head.h可能在項(xiàng)目中被多個(gè)源文件包含(#include “head.h”),而對(duì)于一個(gè)大型項(xiàng)目來說,這些冗余可能導(dǎo)致錯(cuò)誤,因?yàn)橐粋€(gè)頭文件包含類定義或inline函數(shù),在一個(gè)源文件中head.h可能會(huì)被#include兩次(如,a.h頭文件包含了head.h,而在b.c文件中#include a.h和head.h)——這就會(huì)出錯(cuò)(在同一個(gè)源文件中一個(gè)結(jié)構(gòu)體、類等被定義了兩次)。
  • 從邏輯觀點(diǎn)和減少編譯時(shí)間上,都要求去除這些冗余。然而讓程序員去分析和去掉這些冗余,不僅枯燥且不太實(shí)際,最重要的是有時(shí)候又需要這種冗余來保證各個(gè)模塊的獨(dú)立。

為了解決這個(gè)問題,上面代碼中的

#ifndef HEAD_H
#define  HEAD_H
/*……………………………*/
#endif /* HEAD_H */

就起作用了。如果定義了HEAD_H,#ifndef/#endif之間的內(nèi)容就被忽略掉。因此,編譯時(shí)第一次看到head.h頭文件,它的內(nèi)容會(huì)被讀取且給定HEAD_H一個(gè)值。之后再次看到head.h頭文件時(shí),HEAD_H就已經(jīng)定義了,head.h的內(nèi)容就不會(huì)再次被讀取了。

那么下面這段代碼的作用又是什么呢?

#ifdef __cplusplus
extern "C" {
#endif
/*.......*/
#ifdef __cplusplus
}
#endif

我們將在后面對(duì)此進(jìn)行詳細(xì)說明。

關(guān)于 extern “C”

前面的題目中的 __cplusplus 宏,這是C++中已經(jīng)定義的宏,是用來識(shí)別編譯器的,也就是說,將當(dāng)前代碼編譯的時(shí)候,是否將代碼作為 C++ 進(jìn)行編譯。

首先從字面上分析extern “C”,它由兩部分組成:extern關(guān)鍵字、“C”。下面我就從這兩個(gè)方面來解讀extern "C"的含義。

首先,被它修飾的目標(biāo)是 extern 的;其次,被它修飾的目標(biāo)是 C 的。

extern關(guān)鍵字

被 extern “C” 限定的函數(shù)或變量是 extern 類型的。

extern是C/C++語言中表明函數(shù)全局變量作用范圍(可見性)的關(guān)鍵字,該關(guān)鍵字告訴編譯器,其聲明的函數(shù)和變量可以在本模塊或其它模塊中使用。通常,在模塊的頭文件中對(duì)本模塊提供給其它模塊引用的函數(shù)和全局變量以關(guān)鍵字extern聲明。例如,如果模塊B欲引用該模塊A中定義的全局變量和函數(shù)時(shí)只需包含模塊A的頭文件即可。這樣,模塊B中調(diào)用模塊A中的函數(shù)時(shí),在編譯階段,模塊B雖然找不到該函數(shù),但是并不會(huì)報(bào)錯(cuò);它會(huì)在連接階段中從模塊A編譯生成的目標(biāo)代碼中找到此函數(shù)。

被extern修飾的函數(shù),需要在編譯階段去鏈接該目標(biāo)文件,并且與extern對(duì)應(yīng)的關(guān)鍵字是 static,被static修飾的全局變量和函數(shù)只能在本模塊中使用。因此,一個(gè)函數(shù)或變量只可能被本模塊使用時(shí),其一般是不可能被extern “C”修飾的。

**注意:**例如語句 extern int a; 僅僅是對(duì)變量的聲明,其并不是在定義變量 a ,聲明變量并未為 a 分配內(nèi)存空間。定義語句形式為 int a; 變量 a 在所有模塊中作為一種全局變量只能被定義一次,否則會(huì)出現(xiàn)連接錯(cuò)誤。

被 extern “C” 修飾的變量和函數(shù)是按照 C 語言方式編譯和連接的。

由于C++和C兩種語言的親密性,并且早期大量的庫(kù)都是由C語言實(shí)現(xiàn)的,所以不可避免的會(huì)出現(xiàn)在C++程序中調(diào)用C的代碼、C的程序中調(diào)用C++的代碼,但是它們各自的編譯和鏈接的規(guī)則是不同的。

函數(shù)名修飾

  1. 由于Windows下vs的修飾規(guī)則過于復(fù)雜,而Linux下gcc的修飾規(guī)則簡(jiǎn)單易懂,下面我們使用了gcc演示了這個(gè)修飾后的名字。
  2. 通過下面我們可以看出gcc的函數(shù)修飾后名字不變。而g++的函數(shù)修飾后變成【_Z+函數(shù)長(zhǎng)度+函數(shù)名+類型首字母】。

分別使用C的編譯器和C++的編譯器去編譯并獲得一個(gè)可執(zhí)行文件

使用C語言(gcc)編譯器編譯后結(jié)果

使用objdump -S 命令查看gcc生成的可執(zhí)行文件:

image-20220518225738183

使用C++編譯器(g++)編譯后結(jié)果

使用objdump -S 命令查看g++生成的可執(zhí)行文件:

image-20220518225745296

**linux:**修飾后的函數(shù)名= _Z + 函數(shù)名長(zhǎng)度 + 形參類型首字母,Windows下也是相似的,細(xì)節(jié)上會(huì)有所不同,本質(zhì)上都是通過函數(shù)參數(shù)信息去修飾函數(shù)名。

C++的編譯和鏈接方式

采用g++編譯完成后,函數(shù)的名字將會(huì)被修飾,編譯器將函數(shù)的參數(shù)類型信息添加到修改后的名字中,因此當(dāng)相同函數(shù)名的函數(shù)擁有不用類型的參數(shù)時(shí),在g++編譯器看來是不同的函數(shù),而我們另一個(gè)模塊中想要調(diào)用這些函數(shù)也就必須使用C++的規(guī)則去鏈接函數(shù)(找修飾后的函數(shù)名)才能找到函數(shù)的地址。

C的編譯和鏈接方式

對(duì)于C程序,由于不支持重載,編譯時(shí)函數(shù)是未加任何修飾的,而且鏈接時(shí)也是去尋找未經(jīng)修飾的函數(shù)名。

C和C++直接混合編譯時(shí)的鏈接錯(cuò)誤

在C++程序,函數(shù)名是會(huì)被參數(shù)類型信息修飾的,這就造成了它們之間無法直接相互調(diào)用。

例如:

print(int)函數(shù),使用g++編譯時(shí)函數(shù)名會(huì)被修飾為 _Z5printi,而使用gcc編譯時(shí)函數(shù)名則仍然是print,如果直接在C++中調(diào)用使用C編譯規(guī)則的函數(shù),會(huì)鏈接錯(cuò)誤,因?yàn)樗鼤?huì)去尋找 _Z5printi而不是 print。

【C和C++的編譯和鏈接方式的不同】參考:

C++的函數(shù)重載

extern“C”的使用

extern "C"指令非常有用,因?yàn)镃和C++的近親關(guān)系。注意:extern "C"指令中的C,表示的一種編譯和連接規(guī)約,而不是一種語言。

并且extern "C"指令僅指定編譯和連接規(guī)約,并不影響語義,編譯時(shí)仍是一個(gè)C++的程序,遵循C++的類型檢查等規(guī)則。

對(duì)于下面的代碼它們之間是有區(qū)別的

extern "C" void Add(int a, int b);
//指定Add函數(shù)應(yīng)該根據(jù)C的編譯和連接規(guī)約來鏈接
extern void Add(int a, int b);
//聲明在Add是外部函數(shù),鏈接的時(shí)候去調(diào)用Add函數(shù)

如果有很多內(nèi)容要被加上extern “C”,你可以將它們放入extern “C”{ }中。

通過上面的分析,我們知道extern "C"的真實(shí)目的是實(shí)現(xiàn)類C和C++的混合編程,在C++源文件中的語句前面加上extern “C”,表明它按照類C的編譯和連接規(guī)約來編譯和連接,而不是C++的編譯的連接規(guī)約。這樣在類C的代碼中就可以調(diào)用C++的函數(shù)or變量等。

那么混合編譯首先要處理的問題就是要讓我們所寫的C++程序和C程序函數(shù)的編譯時(shí)的修飾規(guī)則鏈接時(shí)的修飾規(guī)則保持一致。

總共就有下面四種情況,也就是說一個(gè)C的庫(kù),應(yīng)該能同時(shí)被C和C++調(diào)用,而一個(gè)C++的庫(kù)也應(yīng)能夠同時(shí)兼容C和C++。

image-20220518225753095

為了展示如上四種情況,我們分別建立一個(gè)C靜態(tài)庫(kù)和C++靜態(tài)庫(kù)。

C程序調(diào)用C的庫(kù),C++程序調(diào)用C++的庫(kù),這是理所應(yīng)當(dāng)?shù)?,因此我們關(guān)注的問題是如何交叉調(diào)用

用法舉例

靜態(tài)庫(kù)是什么

庫(kù)是寫好的現(xiàn)有的,成熟的,可以復(fù)用的代碼。現(xiàn)實(shí)中每個(gè)程序都要依賴很多基礎(chǔ)的底層庫(kù),不可能每個(gè)人的代碼都從零開始,因此庫(kù)的存在意義非同尋常

之所以稱為【靜態(tài)庫(kù)】,是因?yàn)樵阪溄与A段,會(huì)將匯編生成的目標(biāo)文件.o與引用到的庫(kù)一起鏈接打包到可執(zhí)行文件中。因此對(duì)應(yīng)的鏈接方式稱為靜態(tài)鏈接。

試想一下,靜態(tài)庫(kù)與匯編生成的目標(biāo)文件一起鏈接為可執(zhí)行文件,那么靜態(tài)庫(kù)必定跟.o文件格式相似。其實(shí)一個(gè)靜態(tài)庫(kù)可以簡(jiǎn)單看成是一組目標(biāo)文件(.o/.obj文件)的集合,即很多目標(biāo)文件經(jīng)過壓縮打包后形成的一個(gè)文件。靜態(tài)庫(kù)特點(diǎn)總結(jié):

  • 靜態(tài)庫(kù)對(duì)函數(shù)庫(kù)的鏈接是放在編譯時(shí)期完成的。
  • 程序在運(yùn)行時(shí)與函數(shù)庫(kù)再無瓜葛,移植方便。
  • 浪費(fèi)空間和資源,因?yàn)樗邢嚓P(guān)的目標(biāo)文件與牽涉到的函數(shù)庫(kù)被鏈接合成一個(gè)可執(zhí)行文件。

靜態(tài)庫(kù)在程序編譯時(shí)會(huì)被連接到目標(biāo)代碼中,程序運(yùn)行時(shí)將不再需要該靜態(tài)庫(kù),因此體積較大

創(chuàng)建C靜態(tài)庫(kù)

我們以一個(gè)棧的靜態(tài)庫(kù)為例:

首先新建項(xiàng)目Stack_C

image-20220518225759900

新建源文件和頭文件

image-20220518225807539

寫好棧的代碼

注意一定是C程序,即源文件后綴為c

image-20220518225814328

更改輸出文件類型

右鍵項(xiàng)目名稱—>屬性

image-20220518225821196

更改為配置類型為靜態(tài)庫(kù)

image-20220518225828078

生成靜態(tài)庫(kù)

image-20220518225835992

查看是否生成成功

VS一般在項(xiàng)目路徑下的x64\Debug路徑下:

image-20220518225845182

至此,靜態(tài)庫(kù)已經(jīng)可以成功建立了。

再新建一個(gè)項(xiàng)目,寫一個(gè)去調(diào)用該靜態(tài)庫(kù)實(shí)現(xiàn)的棧的程序(以括號(hào)匹配問題為例)

不過對(duì)于VS我們的靜態(tài)庫(kù)是默認(rèn)不去使用的,因此我們需要將靜態(tài)庫(kù)的路徑和庫(kù)的名稱分別添加到庫(kù)目錄和依賴項(xiàng),才能讓程序能去調(diào)用該靜態(tài)庫(kù)。

image-20220518225851175

更改鏈接器配置

右鍵項(xiàng)目名—>點(diǎn)擊屬性

“屬性面板“—>”配置屬性”—> “鏈接器”—>”常規(guī)”,附加依賴庫(kù)目錄中輸入,靜態(tài)庫(kù)所在目錄;

增加庫(kù)目錄(路徑為我們剛剛生成的靜態(tài)庫(kù)所在的Debug文件夾)

image-20220518225858234

增加附加依賴項(xiàng)

名稱為Stack_C項(xiàng)目生成的靜態(tài)庫(kù)名,一般是項(xiàng)目名 + .lib

“屬性面板”—>”配置屬性”—> “鏈接器”—>”輸入”,附加依賴庫(kù)中輸入靜態(tài)庫(kù)名StaticLibrary.lib。

image-20220518225905839

我們先嘗試使用C程序來調(diào)用該靜態(tài)庫(kù)

新建項(xiàng)目

將源文件后綴改為c;包含上Stack_C項(xiàng)目(靜態(tài)庫(kù)項(xiàng)目)的頭文件;點(diǎn)擊生成解決方案;

image-20220518225913686

成功生成,說明成功調(diào)用。

嘗試使用C++程序調(diào)用C靜態(tài)庫(kù)

  • 將源文件后綴改為cpp;
  • 頭文件保持不變;
  • 點(diǎn)擊生成解決方法

結(jié)果報(bào)錯(cuò)了:

image-20220518225924430

這說明在鏈接的過程中出現(xiàn)了問題,也就是在我們的程序找不到靜態(tài)庫(kù)中函數(shù)的地址,原因是我們的靜態(tài)庫(kù)是C語言的,沒有對(duì)函數(shù)進(jìn)行修飾,但在我們的調(diào)用方是C++程序,在鏈接過程中找的是修飾過的函數(shù)名,因此無法找到函數(shù)的地址。

既然C語言的靜態(tài)庫(kù)只能按照C的規(guī)則去編譯這些函數(shù)(即不修飾函數(shù)名),那么我們只要讓C++程序按照C語言的鏈接規(guī)則(即找未經(jīng)修飾的函數(shù)名)去找到函數(shù)名不就解決了?

兩種思路:

  • 改變C庫(kù)的編譯和鏈接方式為C++規(guī)則;
  • 改變C++程序調(diào)用庫(kù)函數(shù)的編譯和鏈接方式為C的規(guī)則;

方法1是不行的,因?yàn)镃語言中可沒有extern “C++”這種東西,那么考慮方法2;

這時(shí)我們可以借助extern“C”改變C++程序的鏈接規(guī)則,讓C++去按照C的規(guī)則去找函數(shù)名,即未經(jīng)過任何修飾的函數(shù)名,那就一定能找到函數(shù)的地址,來去正確調(diào)用靜態(tài)庫(kù)。

在源文件test.cpp使用extern “C”,去改變包含的頭文件中的函數(shù)的鏈接規(guī)則

//調(diào)用庫(kù)的的模塊的頭文件包含
extern "C"
{
	#include"..\..\Stack_C\Stack_C\stack.h"
}
//程序的代碼
//...

那么在test.cpp去鏈接函數(shù)時(shí),就會(huì)直接去找原函數(shù)名。

這樣就解決了。

還有一個(gè)一步到位的解決方法,利用條件編譯,根據(jù)當(dāng)前程序的類型,選擇是否去執(zhí)行extern “C”指令。

  • 調(diào)用方是C程序,不做處理;
  • 調(diào)用方是C++程序,需要使用extern“C”將程序改為C的鏈接規(guī)則;
//調(diào)用庫(kù)的的模塊的頭文件包含
#ifdef __cplusplus//如果是c++程序,就執(zhí)行extern “C”,使用C的鏈接方式,去找未經(jīng)修飾的函數(shù)名
extern "C"{
#endif
#include"..\..\Stack_C\Stack_C\stack.h"
#ifdef __cplusplus
}
#endif
//程序的代碼
//...

但是這樣的處理不太好,我們作為調(diào)用方自然是想可以直接通過頭文件包含的方式去使用庫(kù)里的函數(shù),因此采用下列方法,更改庫(kù)的頭文件函數(shù)聲明為:

#ifdef __cplusplus//如果定義了宏__cplusplus就執(zhí)行#ifdef 到 #endif之間的語句
extern "C"
{
#endif
void StackInit(struct Stack* s);
void StackPush(struct Stack* s, DataType x);
void StackPop(struct Stack* s);
DataType StackTop(struct Stack* s);
int StackSize(struct Stack* s);
void StackDestory(struct Stack* s);
bool StackEmpty(struct Stack* s);
#ifdef __cplusplus
}
#endif

這樣的一段代碼,無論是C++程序還是C程序都可以直接#include就能去調(diào)用該靜態(tài)庫(kù)了。

創(chuàng)建C++靜態(tài)庫(kù)

步驟和創(chuàng)建C的靜態(tài)庫(kù)相同,只不過要將項(xiàng)目中的源文件后綴改為cpp,就會(huì)生成一個(gè)C++的靜態(tài)庫(kù),因此不再闡述。

創(chuàng)建完成后,我們?nèi)允褂脛倓偟捻?xiàng)目,并且添加C++靜態(tài)庫(kù)路徑到庫(kù)目錄,添加C++靜態(tài)庫(kù)名稱到附加依賴項(xiàng),仍然以括號(hào)匹配問題為例去調(diào)用該庫(kù)。(記得刪除C靜態(tài)庫(kù)的庫(kù)目錄和附加依賴項(xiàng),否則我們的程序有可能還會(huì)去調(diào)用C的靜態(tài)庫(kù),這樣我們就無法探究如何去調(diào)用C++靜態(tài)庫(kù)的問題了)

嘗試使用C程序調(diào)用C++靜態(tài)庫(kù)

我們不著急調(diào)用,經(jīng)過先前的經(jīng)驗(yàn),這里可以判斷,C++的程序去調(diào)用C++的庫(kù)一定是沒問題的,但是C程序就不好說了,因此我們要搞定C程序調(diào)用C++庫(kù)的情況,先搞清楚它們的差異:

這里的C++程序去調(diào)用函數(shù)是去尋找修飾后的函數(shù)名,C程序是去找未修飾的函數(shù)名,要想讓它們保持一致有兩個(gè)思路:

改變C程序的編譯和鏈方式為C++的規(guī)則;改變C++靜態(tài)庫(kù)的編譯方式為C的規(guī)則;

但是方法1是不行的,之前也說過,C語言中沒有extern “C++”這種東西,那么考慮方法2;

對(duì)庫(kù)的頭文件中的函數(shù)做如下處理:

//用C的規(guī)則去搞庫(kù)的編譯和鏈接方式
extern "C"
{
	void StackInit(struct Stack* s);
	void StackPush(struct Stack* s, DataType x);
	void StackPop(struct Stack* s);
	DataType StackTop(struct Stack* s);
	int StackSize(struct Stack* s);
	void StackDestory(struct Stack* s);
	bool StackEmpty(struct Stack* s);
}

那么現(xiàn)在C++的靜態(tài)庫(kù)的函數(shù)名都是沒有經(jīng)過修飾的。(C的規(guī)則)

但是我們?nèi)ゾ幾g仍然報(bào)錯(cuò):

error C2059: 語法錯(cuò)誤:“字符串”

"StackInit”未定義;假設(shè)外部返回int

“StackPush”未定義;假設(shè)外部返回int

“StackEmpty”未定義;假設(shè)外部返回int

“StackTop”未定義;假設(shè)外部返回int

“StackPop”未定義;假設(shè)外部返回int

這是因?yàn)槲覀兪褂肅程序時(shí)也包含了此頭文件,但是C語言中無法識(shí)別extern“C”,因此報(bào)錯(cuò)。

我們嘗試使用條件編譯來決定是否使用extern“C”,根據(jù)調(diào)用方的不同改變函數(shù)鏈接規(guī)則:

  • 調(diào)用方是C++程序,那么需要使用extern“C”將C++程序的函數(shù)鏈接規(guī)則變?yōu)镃的;
  • 調(diào)用方是C程序,不使用extern“C”語句;

因此我們做如下處理,將庫(kù)的頭文件中的函數(shù)聲明加上:

#ifdef __cplusplus//如果定義了宏__cplusplus就執(zhí)行#ifdef 到 #endif之間的語句
extern "C"
{
#endif
void StackInit(struct Stack* s);
void StackPush(struct Stack* s, DataType x);
void StackPop(struct Stack* s);
DataType StackTop(struct Stack* s);
int StackSize(struct Stack* s);
void StackDestory(struct Stack* s);
bool StackEmpty(struct Stack* s);
#ifdef __cplusplus
}
#endif

總結(jié):C++和C之間的混合編譯,為了消除函數(shù)名修飾規(guī)則不同的的差別,我們需要使用extern ”C“來改變C++的編譯和連接方式。

但這樣問題也隨之而來:

C++的庫(kù)就失去了函數(shù)重載的特性,如果庫(kù)中有同名函數(shù),那么就無法正確編譯,因?yàn)榘凑誄的方式去編譯,函數(shù)名會(huì)沖突。

如何解決這個(gè)問題呢?

實(shí)際上這個(gè)問題無法解決,一旦選擇了將某個(gè)函數(shù)指定了按照C的方式去編譯鏈接,那么這個(gè)函數(shù)就已經(jīng)失去了重載的特性了,不過Cpp的庫(kù)中未被指定按照C的規(guī)則去編譯和鏈接的那些函數(shù),仍然可以被重載,并且具有C++的一切特性。

因此這個(gè)問題無解,只有通過避免“一刀切”的方法來保護(hù)那些我們想重載的函數(shù),也就是說一部分庫(kù)里的函數(shù)那就是實(shí)現(xiàn)給C程序調(diào)用的,我們就通過extern“C”改變它的編譯和鏈接方式,而對(duì)于那些實(shí)現(xiàn)給C++程序調(diào)用的函數(shù)接口,我們不做任何處理,并且不暴露給C程序。

想要實(shí)現(xiàn)上述過程,我們需要在靜態(tài)庫(kù)項(xiàng)目中創(chuàng)建兩個(gè)頭文件libc.hlibcpp.h,libc.h聲明那些需要暴露給C程序的函數(shù)接口,并且使用上面介紹的條件編譯和extern“C”,libcpp.h聲明那些暴露給給Cpp程序的函數(shù)接口,這樣兩個(gè)頭文件的函數(shù)的鏈接規(guī)范互不相同,也互不干擾。只需要將lic.h在C程序調(diào)用的地方使用#include 包含,libcpp.h在C++程序調(diào)用的地方使用#include包含即可使用。

因此C++庫(kù)中哪個(gè)接口需要暴露給C,我們就用extern“C”修飾哪個(gè)接口。

image-20220518225938546

總之,C的庫(kù)可以給C程序和C++程序調(diào)用,而C++庫(kù)也可以被C程序和C++程序調(diào)用

如果要滿足這個(gè)庫(kù)中所有的函數(shù)都能同時(shí)被C++和C調(diào)用,那么無論是C的庫(kù)還是C++的庫(kù),最終這個(gè)庫(kù)的編譯和鏈接方式都只能是C的規(guī)范,因?yàn)镃++可以使用C的鏈接規(guī)范但是C不能使用C++的鏈接規(guī)范,也就導(dǎo)致了如果庫(kù)的鏈接規(guī)范是C++的,那么無論如何,C程序都無法調(diào)用。

值得一提的是C++程序中的函數(shù)可以使用兩種鏈接規(guī)范,因此我們可以針對(duì)函數(shù)的使用場(chǎng)景來選擇該函數(shù)的編譯和鏈接規(guī)范,使得一部分函數(shù)保留C++的特性,但一部分函數(shù)就只能為了兼容C而犧牲C++的特性,想要既兼容C又保留C++的特性,這是做不到的。

到此這篇關(guān)于C++和C的混合編譯的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)C++和C混合編譯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • C++超詳細(xì)講解逗號(hào)操作符

    C++超詳細(xì)講解逗號(hào)操作符

    使用逗號(hào)運(yùn)算符是為了把幾個(gè)表達(dá)式放在一起。整個(gè)逗號(hào)表達(dá)式的值為系列中最后一個(gè)表達(dá)式的值。從本質(zhì)上講,逗號(hào)的作用是將一系列運(yùn)算按順序執(zhí)行
    2022-05-05
  • C語言實(shí)現(xiàn)用戶態(tài)線程庫(kù)案例

    C語言實(shí)現(xiàn)用戶態(tài)線程庫(kù)案例

    下面小編就為大家?guī)硪黄狢語言實(shí)現(xiàn)用戶態(tài)線程庫(kù)案例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • C語言中數(shù)據(jù)的存儲(chǔ)詳解

    C語言中數(shù)據(jù)的存儲(chǔ)詳解

    這篇文章主要為大家介紹了C語言中數(shù)據(jù)的存儲(chǔ),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助,希望能夠給你帶來幫助
    2021-11-11
  • VS2019編寫C程序或者CUDA程序出現(xiàn)“無法啟動(dòng)程序,系統(tǒng)找不到指定的文件”問題的詳細(xì)解決方法

    VS2019編寫C程序或者CUDA程序出現(xiàn)“無法啟動(dòng)程序,系統(tǒng)找不到指定的文件”問題的詳細(xì)解決方法

    這篇文章主要介紹了VS2019編寫C程序或者CUDA程序出現(xiàn)“無法啟動(dòng)程序,系統(tǒng)找不到指定的文件”問題的詳細(xì)解決方法,文中通過圖文的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 關(guān)于C++友元函數(shù)的實(shí)現(xiàn)講解

    關(guān)于C++友元函數(shù)的實(shí)現(xiàn)講解

    今天小編就為大家分享一篇關(guān)于關(guān)于C++友元函數(shù)的實(shí)現(xiàn)講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C++中兩種字符串定義方式和區(qū)別介紹

    C++中兩種字符串定義方式和區(qū)別介紹

    大家好,本篇文章主要講的是C++中兩種字符串定義方式和區(qū)別介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • 用C語言如何打印一個(gè)等腰三角形

    用C語言如何打印一個(gè)等腰三角形

    這篇文章主要介紹了用C語言如何打印一個(gè)等腰三角形,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語言入門篇--初識(shí)結(jié)構(gòu)體

    C語言入門篇--初識(shí)結(jié)構(gòu)體

    本篇文章是基礎(chǔ)篇,適合c語言剛?cè)腴T的朋友,本文對(duì)c語言的結(jié)構(gòu)體做了簡(jiǎn)單的分析,幫助大家快速入門c語言的世界,更好的理解c語言
    2021-08-08
  • C語言獲取文件長(zhǎng)度的方法

    C語言獲取文件長(zhǎng)度的方法

    這篇文章主要介紹了C語言獲取文件長(zhǎng)度的相關(guān)知識(shí),包括使用標(biāo)準(zhǔn)庫(kù)方法和使用Linux系統(tǒng)調(diào)用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • C++實(shí)現(xiàn)二維圖形的打印

    C++實(shí)現(xiàn)二維圖形的打印

    大家好,本篇文章主要講的是C++實(shí)現(xiàn)二維圖形的打印,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02

最新評(píng)論