1. 程式人生 > >C/C++函式名稱修飾規則及extern "C"的作用(函式名壓扎)

C/C++函式名稱修飾規則及extern "C"的作用(函式名壓扎)

一、函式名稱修飾規則

函式的名字修飾(Decorated Name)就是編譯器在編譯期間建立的一個字串,用來指明函式的定義或原型。LINK程式或其他工具有時需要指定函式的名字修飾來定位函式的正確位置。由於c語言不支援函式過載,而c++語言支援函式過載,所以c和c++的函式名稱修飾規則是不相同的。

以下面這個Add函式為例,來探討一下c和c++語言的函式名稱修飾規則。

  1. int Add(int x, int y)  
  2. {  
  3.     return x+y;  
  4. }  

c語言的函式名稱修飾規則:

 [window系統下vs2010]:(在對映檔案.map中可以檢視,需要右擊當前工程  --〉屬性--〉配置屬性--〉連結器 --〉除錯 --〉生成對映檔案 修改為  “是 (/MAP)” ,然後執行程式在當前工程的Debug資料夾中就會生成一個.map的檔案)。

  c語言將上面的函式名稱處理為_Add,即其修飾規則為_函式名(函式名前加_)。

 [Centos]:(利用objdump命令可以檢視目標檔案中的函式名字的修飾)。

c語言將上面的函式名稱處理為Add,即為函式名。

c++語言的函式名稱修飾規則:

  [window系統下vs2010]:

  c++語言將上面的函式名稱處理為[email protected]@[email protected]  (這個叫做函式名壓扎)

(1)其中‘?’標識函式名的開始,其後跟函式名;

(2)“@@YA”標識引數表的開始,其後跟的第一個字元代表函式的返回值型別,接下來的字元依次代表函式引數列表中各個引數的型別;

        型別的代號:

         x--void   ,   
         d--char,   
         e--unsigned   char,   
         f--short,   
         h--int,   
         i--unsigned   int,   
         j--long,   
         k--unsigned   long,   
         m--float,   
         n--double,   
        _n--bool,   
        ...  ...

        所以@@yg後面的HHH分別代表三個int型別,其中第一個為函式返回值,上下兩個為引數型別。

(3)@z標識整個名字結束。

 [Centos]:

c++語言將上面的函式名稱處理為_Z3Addii

其中_Z代表開始,3代表函式名的字元個數,其後跟函式名(這裡為Add),再加上引數型別(這裡ii代表有兩個整型的引數)。

       通過上面的分析,我們發現不同的編譯器對函式名稱修飾的規則是不同的,但我們依然可以找到規律,c語言對函式名稱修飾的處理只關注到了函式名;而c++語言除了函式名,還關注了函式的引數,通過對函式名稱的修飾不同,編譯器呼叫函式時所找的符號就不同,因而c++語言支援函式過載。也可得出構成函式過載的條件為函式名相同,引數不同,返回值型別可同可不同。

二、extern "C" 的作用

那麼,就有一個問題,在c++檔案中可以直接利用extern使用c檔案中的程式碼嗎?

Add.c

  1. int Add(int x, int y)  
  2. {  
  3.     return x+y;  
  4. }  

Test.cpp

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. externint Add(int x, int y);  
  4. int main()  
  5. {  
  6.     int z = Add(1, 2);  
  7.     printf("%d\n", z);  
  8.     system("pause");  
  9.     return 0;  
  10. }  


上面這樣使用可以嗎?  哎呦,壞了,出現了這個錯誤:error LNK2019: 無法解析的外部符號 "int __cdecl Add(int,int)" ([email protected]@[email protected]),該符號在函式 _main 中被引用。

我們來分析一下,Add函式在Add.c這個檔案中,編譯時Add函式被處理為_Add。在Test.cpp檔案中我們告訴編譯器我們在別的檔案中定義了Add函式,但是Test.cpp這個檔案將Add函式處理為[email protected]@[email protected],所以當買你函式中呼叫到Add函式時編譯器就在別的檔案中一直找[email protected]@[email protected],發現沒有找到。其實在別的檔案中Add函式被處理為了_Add,所以肯定找不到了,長的都不一樣嘛!!

那麼,為了讓編譯器能夠找到.c檔案中的函式,我們該怎麼辦呢??

拿出我們的法寶extern "C",就是將Test.c檔案中extern int Add(int x, int y);變為extern "C" int Add(int x, int y);

使用extern "C" 相當於告訴編譯器這部分程式碼使用c語言的規則進行編譯和連結。這樣cpp檔案中的Add函式就會被處理為_Add,編譯器就能在Add.c檔案中找到它了。

相關推薦

C/C++函式名稱修飾規則extern "C"的作用(函式)

一、函式名稱修飾規則 函式的名字修飾(Decorated Name)就是編譯器在編譯期間建立的一個字串,用來指明函式的定義或原型。LINK程式或其他工具有時需要指定函式的名字修飾來定位函式的正確位置。由於c語言不支援函式過載,而c++語言支援函式過載,所以c和c++的函

函式呼叫約定與函式名稱修飾規則(一)

    作者:星軌(oRbIt)    E_Mail:[email protected]    轉載請註明原作者,否則請勿轉載       使用C/C++語言開發軟體的程式設計師經常碰到這樣的問題:有時候是程式編譯沒有問題,但是連結的時候總是報告函式不存在(經典的L

資料夾中所有圖片名稱的修改剪裁 C++

在進行影象識別時,需要對INRIA資料集進行剪裁,同時修改資料集的名稱便於進行影象的識別與訓練,在網上看到一個看到一個小程式處理圖片挺好使得,進行修改,程式如下 #include <iostream> #include <fstream&

C++ 輸入流 cin/ ifstream/ istringstream 幾個相關函式在遇到檔案結束符EOF時的行為

以下內容分別在VC6.0 和 g++ 4.7下測試: 輸入流在遇到檔案結束符時會設定其eofbit,但此時在兩個編譯器上直接測試流得到的結果都為真,同時eof()也為真,舉例如下: #include <iostream> #include <string&

c呼叫c++函式,為什麼要加extern c

首先,作為extern是C/C++語言中表明函式和全域性變數作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其宣告的函式和變數可以在本模組或其它模組中使用。 通常,在模組的標頭檔案中對本模組提供給其它模組引用的函式和全域性變數以關鍵字extern宣告。例如,如果模組B欲引

c++程式中呼叫被c編譯器編譯後的函式,為什麼要加extern "c"?

首先,被它修飾的目標是“extern”的。也就是告訴編譯器,其宣告的函式和變數可以在本模組或其他模組中使用。通常,在模組的標頭檔案中對本模組提供給其他模組引用的函式和全域性變數以關鍵字extern宣告。 其次,被它修飾的目標是“c”,意思是其修飾的變數和函式是按照c語言方式

python - 函式的相互呼叫 變數的作用

# -*- coding:utf-8 -*-'''@project: jiaxy@author: Jimmy@file: study_函式的相互呼叫及變數的作用域.py@ide: PyCharm Community Edition@time: 2018-11-10 10:04@blog: https://ww

C/C++函式符號生成規則函式修飾);C++ 函式過載

         函式符號(函式的名字修飾):在編譯階段生成的字串,來指明函式的定義或原型 。 C函式符號生成規則: _cdel呼叫約定(C標準呼叫約定):函式名前加下劃線。 _stdcall呼叫約定:函式名前加下劃線,函式名後加“@”符號和其引數位元組。 _fast

C/C++變數函式的命名規則

一、C語言變數名的命名規則:(可以字母,數字,下劃線混合使用) 1. 只能以字母或下劃線開始; 2. 不能以數字開始; 3. 一般小寫; 4. 關鍵字不允許用(eg:int float=2//error  float 為保留字不允許用); 二、函式名的命名規則 1.見名知意; 2.自定義函式函式名首字母大寫(

C++ 編譯器的函數修飾規則

_cdecl 開始 cti amp asc 編碼 常常 匹配 AC 函數名字修飾(Decorated Name)方式 函數的名字修飾(Decorated Name)就是編譯器在編譯期間創建的一個字符串,用來指明函數的定義或原型。LINK程序或其他工具有時需要指定函數的名

C語言中static修飾函式和普通函式的區別

用static修飾的函式,本限定在本原始碼檔案中,不能被本原始碼檔案以外的程式碼檔案呼叫。而普通的函式,預設是extern的,也就是說,可以被其它程式碼檔案呼叫該函式。 在函式的返回型別前加上關鍵字static,函式就被定義成為靜態函式。普通 函式的定義和宣告預設情況下是extern的,但靜

C語言】記憶體分配函式malloc/ calloc/ realloc記憶體釋放free

前言: 記憶體區域劃分與分配: 1、棧區(stack)——程式執行時由編譯器自動分配,存放函式的引數值,區域性變數的值等,程式結束時由編譯器自動釋放。 2、堆區(heap) —— 在記憶體開闢另一塊儲存區域。一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可

C++建構函式詳解顯示呼叫建構函式

                         

C++關鍵字、名稱空間、函式過載、預設引數、行內函數、引用

一 .C++入門 1.C++關鍵字 2.名稱空間 3.C++輸入&輸出 4.預設引數 5.函式過載 6.引用 7.行內函數 8.auto關鍵字 9.基於範圍的for迴圈 10.指標空值nullptr&nullptr_t 二. 正文 1.C++關鍵字(C++98)   

atoi函式的用法C語言實現ato

庫函式原型: #inclue <stdlib.h> int atoi(const char *nptr); 用法:將字串裡的數字字元轉化為整形數。返回整形值。 注意:轉化時跳過前面的空格字元,直到遇上數字或正負符號才開始做轉換,而再遇到非數字或字串結束時('/0')才結束

c++ 中cin get getline等函式的使用規則

在學習C++的過程中,經常會遇到輸入輸出的問題,以下總結一下下面幾個函式的用法:  1)、cin  2)、cin.get()  3)、cin.getline()  4)、getline()  5)、gets() 1、cin>>&nbs

c語言動態分配記憶體記憶體分配部分函式

#include<stdio.h> /** 在C中動態分配記憶體的基本步驟有: 1,用malloc類的函式分配記憶體; 2,用這些記憶體支援應用程式 3,用free函式釋放記憶體 二、動態記憶體分配函式     malloc :從堆上分配記憶體 &nbs

C++學習筆記——名稱空間&預設引數&函式過載&引用

C++學習筆記——名稱空間&預設引數&函式過載&引用 戳這裡:我的印象筆記原連結 C++: 1.解決C語言中設計不好或者使用不是很方便的語法—>優化 2.增加新的語法特性 注:extern “C”:在C++工程中,將程式碼按照C語言的風格來編譯

C語言呼叫C++中的函式extern "C"的含義

C++編譯器在將cpp檔案編譯成庫時,匯出的函式名會改變,成員函式會通過加一些元素變成全域性函式,如果這時候我們需要用C語言呼叫C++的函式, 就有了一個問題,那就是不知道C++庫中匯出的函式名,這是由編譯器決定的,這個時候就需要用到extern關鍵字。例子: test.c

C# 小數點後保留兩位小數,四捨五入的函式使用方法

1 Math.Round(45.367,2) //Returns 45.37 2 Math.Round(45.365,2) //Returns 45.36  C#中的Round()不是我們中國人理解的四捨五入,是老外的四捨五入,是符合IEEE標準的四