日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

在C++编译器下,将代码按照C语言编译

發布時間:2024/1/1 c/c++ 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在C++编译器下,将代码按照C语言编译 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

extern "C"的使用

  • 一、定義-defintion
  • 二、extern "C"使用舉例-example
  • 三、extern "C"的用武之處在哪?
  • 四、extern "C"常用特性
    • 1.C++調用第三方庫(含.h&.c文件)
    • 2. C語言也調用第三方庫(含.h&.c文件)
      • a. #define __cplusplus解釋
      • b. #ifdef條件編譯
      • c. 啟示
  • 五、不相關學習tips
    • 1.防止某個.h文件被重復include
    • 2.防止某個.h文件被重復include(#pragma)

一、定義-defintion

被extern "C"修飾的代碼會按照C語言的方式去編譯

二、extern "C"使用舉例-example

我們都知道,C語言不支持函數重載,只有C++才支持函數重載。下方兩個函數就會按照C語言進行編譯,由于是重載函數,所以會報錯

extern "C" void function(int v1, double v2) {cout << "int v1, double v2" << endl; } extern "C" void function(double v1, int v2) {cout << "double v1, int v2" << endl; }int main(int argc, char **argv) {function(10,10.0);//會報錯,因為C語言不支持函數重載getchar();return 0; }

三、extern "C"的用武之處在哪?

  • 由于C、C++編譯方式的不同,這種機制往往用在C\C++混合開發,往往做項目時,可能會用到第三方庫:這個庫可能是C語言寫的,這時候這種機制就很重要。
第三方庫math.c文件,提供了一個函數,但用的C語言寫的 int sum(int v1,int v2) {return v1 + v2; } my.cpp自己的cpp工程文件,想要調用math.c里的函數為我所用int sum(int v1,int v2);//聲明一下 //C++編譯器一看到這個函數,可能就直接name manuling了,改成了sum_i_iint main() {sum(1,1);getchar();return 0; } //這時候就會出錯,因為C語言編譯規則和C++編譯規則不相同。可能C++看到sum的函數聲明,直接把名字改成sum_i_i,而C語言中的名字就是sum,所以C++編譯器就會找不到函數,就會報錯。
  • 我還是想要用第三方庫里的函數,怎么辦呢?這時候就要借助extern “C”
第三方庫math.c文件,提供了一個函數,但用的C語言寫的 int sum(int v1,int v2) {return v1 + v2; } my.cpp自己的cpp工程文件,想要調用math.c里的函數為我所用extern "C" int sum(int v1,int v2);//聲明一下 //這里我要告訴C++編譯器,這個函數是C語言編譯的,你不要亂改名字了。如此,就可以實現C++環境調用C語言里的東西int main() {sum(1,1);//2getchar();return 0; }

四、extern "C"常用特性

1.C++調用第三方庫(含.h&.c文件)

函數如果同時有聲明(.h文件)和實現(.c),extern “C"修飾只放在函數聲明中,即.c文件實現函數時,可以不用再次修飾。如果.cpp文件引用.h中的C語言函數時:如果.h的函數已經被extern “C"修飾,則直接#include””;如果沒有被修飾,則必須extern “C” #include""

  • .h頭文件中的函數聲明沒有被extern "C"修飾
AAA.h文件 void func_c();//聲明時不用extern "C"修飾,那#include時就要用extern "C"修飾 AAA.c文件 void func_c()//實現 {//函數體 } AAA.cpp文件 extern "C" #include"AAA.h"//由于AAA.h文件中的函數沒有被extern "C" 修飾,所以想要這個函數按照C語言編譯,就必須將include轉換。int main() {func_c();getchar();return 0; }
  • .h頭文件中的函數聲明有被extern "C"修飾
AAA.h文件 extern "C" void func_c();//聲明時用extern "C"修飾,那#include時就不用extern "C"修飾 AAA.c文件 void func_c()//實現 {//函數體 } AAA.cpp文件 #include"AAA.h"//由于AAA.h文件中的函數有被extern "C" 修飾,因此這里直接include就可以int main() {func_c();getchar();return 0; }

有函數聲明和實現時,想要某個函數采用C語言編譯,最好只在函數聲明前采用extern “C” 修飾,在函數實現前不做任何操作

2. C語言也調用第三方庫(含.h&.c文件)

由于整個項目C++需要調用第三方庫(第三方庫是用C語言寫的),所以用extern “C” 修飾一下這個第三方庫里的函數,即可被C++調用。但,我這個項目里如果有.c文件也需要調用這個第三方庫,可以直接調用嗎?答案是不能的,因為這個第三方庫函數已經被extern “C” 修飾了,而C語言是不認識extern “C” 的。

我希望這個第三方庫更加的靈活,即C++調用函數時自動加上extern “C” 修飾;C語言調用,extern “C” 自動去掉

a. #define __cplusplus解釋

#define __cplusplus這個宏被默認的編寫在C++文件的最開頭,用來確認這個文件是cpp文件。只要你是cpp文件,第一行編譯器默認給你寫了一句#define __cplusplus。

b. #ifdef條件編譯

#ifdef 和 #endif // 組合使用,達到條件編譯的目的。下方代碼的最終結果就是:如果某個cpp文件調用這段代碼,才會編譯代碼段,c文件調用這段代碼,不會編譯這段代碼段,即只讀到了一對注釋

#ifdef __cplusplus //被編譯的代碼段,如果定義了名為__cplusplus的宏,這段代碼段才會被編譯,否則會被編譯器視為注釋 #endif // __cplusplus
  • 于是第三方庫的完美寫法是這樣的:
AAA.h文件 #ifdef __cplusplus extern "C" { #endif // __cplusplusvoid func_c();//聲明時用extern "C"修飾,那#include時就不用extern "C"修飾#ifdef __cplusplus } #endif // __cplusplus AAA.c文件 void func_c()//實現 {//函數體 } AAA.cpp文件 #include"AAA.h"//由于AAA.h文件中的函數有被extern "C" 修飾,因此這里直接include就可以 因為是c++環境,所以AAA.h里的代碼是這樣的:extern "C" {void func_c();//因為C++環境在此之前定義了宏 __cplusplus,所以extern "C"代碼被編譯保存了下來}int main() {func_c();getchar();return 0; } other.c文件,也需要調用第三方庫AAA.h里的函數 #include"AAA.h" //因為是c語言環境,所以AAA.h里的代碼是這樣的://extern "C" {void func_c();//} //這是因為.C文件里的最開始沒有宏定義 __cplusplus int main() {func_c();getchar();return 0; }

c. 啟示

以后凡是用C語言編寫的第三方庫,最好都要按照下述代碼改動.h文件。這樣的話,C++和C語言文件都可以調用這個第三方庫,不僅不會出錯,還會使得代碼更加規范

//第三方C語言庫 #ifdef __cplusplus extern "C" { #endif // __cplusplusvoid function1(); void function2(); void function3(); void function4(); void function5(); ..... #ifdef __cplusplus } #endif // __cplusplus

五、不相關學習tips

1.防止某個.h文件被重復include

我們在開發的時候,當代碼量很大時,我們可能會在中間include頭文件,下面的組合會解決這個問題
#ifndef BBB
#define BBB
…BBB.h頭文件代碼
#endif //!BBB

  • 錯誤示例
BBB.h文件 //代碼 某個.cpp文件 #include<BBB.h> ... 可能有很多行代碼 ...#include<BBB.h>//我在某處又引入了這個頭文件,這時候就會報錯,因為我重復包含了.h文件 ...
  • 正確且規范的編寫.h頭文件。
BBB.h文件 #ifndef BBB //如果沒有定義BBB這個宏 #define BBB //定義BBB這個宏,然后下面代碼參與編譯//代碼#endif //!BBB

#include<BBB.h>就相當于把BBB.h文件中的代碼全部拷貝一份

某個.cpp文件 #include<BBB.h> //#ifndef BBB //如果沒有定義BBB這個宏 //#define BBB //定義BBB這個宏,然后下面代碼參與編譯代碼//#endif //!BBB ... 可能有很多行代碼,然后我忘了前面已經#include<BBB.h>了,我又包含了一遍 ...#include<BBB.h>//我在某處又引入了這個頭文件,這時候就會報錯,因為我重復包含了.h文件 //#ifndef BBB //如果沒有定義BBB這個宏,直接判斷失敗,因為上面已經#define BBB了一次,所以在#endif //!BBB之前的代碼都不會編譯了 //#define BBB //定義BBB這個宏,然后下面代碼參與編譯代碼//#endif //!BBB ...

2.防止某個.h文件被重復include(#pragma)

新建.h頭文件時第一行出現的 #pragma once,是為了防止這個.h文件被重復包含,即也是防止cpp文件中多次包含相同的.h文件。#pragma once可以起到和上述相同的作用

#pragma once 會被定義在.h文件的開頭,也會起到防止被重復include的錯誤。但與上面的#ifndef的區別是什么呢?

#pragma once 和 #ifndef + #define + #endif //! 的區別在于,后者什么編譯器都支持,而前者則必須保證GCC3.4版本之后的編譯器才支持。同時前者只能針對整個頭文件,而后者可以針對文件中的部分代碼。

總結

以上是生活随笔為你收集整理的在C++编译器下,将代码按照C语言编译的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。