在c++程式中呼叫被C編譯器編譯後的函式,為什麼要使用extern “C”

gogogo_sky發表於2017-05-04

c/c++函式呼叫約定:c/c++函式呼叫約定
一、原題:
這裡寫圖片描述
二、詳細說明:
現在,在一個工程中;有一個test.c檔案;一個test1.cpp檔案;

//test.c

#include<stdio.h>

int Add(int a,int b)
{
    return a+b;
}

(1)使用extern int Add(int,int);宣告外部函式—–錯誤
//test1.cpp

#include<iostream>
using namespace std;
extern int Add(int,int);//宣告外部test.c中的函式
int main()
{
    cout<<Add(50,50)<<endl;
    return 0;
}

執行結果:錯誤
錯誤:1>test.obj : error LNK2019: 無法解析的外部符號 “int __cdecl Add(int,int)” (?Add@@YAHHH@Z),該符號在函式 _main 中被引用

解釋:

c語言程式和c++程式在編譯時,是相互獨立的編譯;在.c檔案中,編譯器將Add函式重新命名為_Add; 而在.cpp檔案中,編譯器將用extern宣告的函式重新命名為(?Add@@YAHHH@Z);那麼在連結階段,在_mian函式中該Add函式被呼叫;
此時編譯器帶著(?Add@@YAHHH@Z)函式名進入test.c檔案的編譯檔案中去尋找(?Add@@YAHHH@Z)函式,但是在test.c檔案中這個Add函式被編譯器重新命名為_Add,由於在.cpp檔案中和.c檔案中同一個函式名被編譯器重新命名後的名字不一樣;所以.cpp檔案宣告的外部函式找不到真正定義的地方;程式錯誤;
(2)使用extern "C" int Add(int,int); 外部函式—-正確

#include<iostream>
using namespace std;
extern "C" int Add(int,int);
int main()
{
    cout<<Add(50,50)<<endl;
    return 0;
}

解釋:
c++語言為了支援過載,對編譯時函式的重新命名規則進行更改,
使用extern “C” 的方式在c++程式中宣告c語言檔案中的函式,可以在編譯時,告訴編譯器使用C語言的規則對該函式的的函式名的進行重新命名,這樣在連結的時候,就可以順利在.c檔案中找到該函式;

相關文章