装飾名
C および C++ プログラム内の関数、データ、オブジェクトは、内部ではそれぞれの装飾名で表されます。 "装飾名" は、オブジェクト、データ、または関数定義のコンパイル中にコンパイラによって作成される、エンコードされた文字列です。 これにより、呼び出し規約、型、関数のパラメーター、およびその他の情報が、名前と共に記録されます。 こういった名前の装飾は、"名前修飾" とも呼ばれ、リンカーが実行可能ファイルをリンクするとき、正しい関数やオブジェクトを見つけるために役立ちます。
装飾名の名前付け規則は、Visual Studio のさまざまなバージョンごとに変化しており、ターゲット アーキテクチャによっても異なる場合があります。 Visual Studio を使用して作成されたソース ファイルと正しくリンクするには、C および C++ の DLL とライブラリを、同じコンパイラ ツールセット、フラグ、およびターゲット アーキテクチャを使用してコンパイルする必要があります。
Note
Visual Studio 2015 以降でビルドされたライブラリは、Visual Studio 2022 を介して新しいバージョンの Visual Studio でビルドされたアプリケーションで使用できます。 詳細については、「Visual Studio のバージョン間の C++ バイナリ互換性」を参照してください。
修飾名の使用
正常にコンパイルされ、リンクされるコードを記述するために、通常は装飾名を把握している必要はありません。 装飾名は、コンパイラおよびリンカー内部の実装の詳細です。 通常、ツールは非装飾形式の名前を処理できます。 ただし、リンカーやその他のツールに関数名を指定するときは、装飾名が必要な場合もあります。 たとえば、オーバーロードされた C++ 関数、名前空間のメンバー、クラス コンストラクター、デストラクターと、特殊メンバー関数を一致させるには、装飾名を指定する必要があります。 オプション フラグとその他の装飾名が必要な状況の詳細については、使用しているツールとオプションのドキュメントを参照してください。
関数名、クラス、呼び出し規約、戻り値の型、またはいずれかのパラメーターを変更する場合、装飾名も同様に変更されます。 この場合、新しい装飾名を取得し、それを装飾名が指定されているすべての場所で使用する必要があります。
名前の装飾は、他のプログラミング言語で記述されたコードにリンクする場合や、他のコンパイラを使用する場合にも重要です。 コンパイラによって、使用する名前装飾規約は異なります。 実行可能ファイルを別の言語で記述されたコードにリンクする場合、エクスポートおよびインポートされた名前と呼び出し規約を一致させるには、特別な配慮が必要です。 アセンブリ言語のコードを MSVC を使って記述されたソース コードにリンクするには、MSVC の装飾名と呼び出し規則を使用する必要があります。
C++ 修飾名の形式
C++ の関数の装飾名には、次の情報が含まれます。
関数名。
メンバー関数の場合、関数がメンバーであるクラス。 装飾には、関数を含むクラスを囲むクラスを含めることができます。
関数が属する名前空間 (名前空間の一部である場合)。
関数のパラメーターの型。
呼び出し規則
関数の戻り値の型。
省略可能なターゲット固有の要素。 ARM64ECオブジェクトでは、
$$h
タグが名前に挿入されます。
装飾名では、関数とクラスの名前はエンコードされます。 装飾名の残りの部分は、コンパイラとリンカーに対してのみ内部的な意味を持つコードです。 C++ の非装飾名および装飾名の例を次に示します。
非装飾名 | 装飾名 |
---|---|
int a(char){int i=3;return i;}; |
?a@@YAHD@Z |
void __stdcall b::c(float){}; |
?c@b@@AAGXM@Z |
C 装飾名の形式
C の関数の装飾形式は、次の表に示すように、その宣言で使用される呼び出し規則によって決まります。 また、C++ コードが extern "C"
リンケージを持つよう宣言されている場合に使用される装飾形式でもあります。 既定の呼び出し規約は __cdecl
です。 64 ビット環境では、C または extern "C"
関数は、 __vectorcall
呼び出し規則を使用する場合にのみ修飾されます。
呼び出し規約 | 装飾 |
---|---|
__cdecl |
先頭に下線 (_ ) |
__stdcall |
先頭に下線 (_ ) があり、末尾にはアット マーク (@ ) と、その後にパラメーター リスト内のバイト数が 10 進数で続きます |
__fastcall |
先頭と末尾にアット マーク (@ ) があり、その後ろにパラメーター リスト内のバイト数を表す 10 進数が続きます |
__vectorcall |
末尾に 2 つのアット マーク (@@ ) があり、その後にパラメーター リスト内のバイト数が 10 進数で続きます |
C リンケージを持つARM64EC関数の場合 (C としてコンパイルされるか、 extern "C"
を使用するかに関係なく)、修飾名の前に #
が付加されます。
装飾された名前を表示する
データ、オブジェクト、関数定義、または関数プロトタイプを含むソース ファイルをコンパイルした後に、装飾形式のシンボル名を取得できます。 プログラム内の修飾名を確認するために、次のいずれかのメソッドを使用できます。
リスティング ファイルを使用して装飾名を確認するには
/FA
(リスト ファイルの種類)、コンパイラ オプションをソース コード (/FAs
) でアセンブリに設定データ、オブジェクト、または関数の定義またはプロトタイプを含むソース ファイルをコンパイルして、一覧を生成します。たとえば、開発者コマンド プロンプトに「
cl /c /FAs example.cpp
」と入力して、登録情報ファイルを生成example.asm
。結果の一覧ファイルで、
PUBLIC
で始まり、セミコロン (;
) の後に非コーディングのデータまたは関数名が続く行を見つけます。PUBLIC
とセミコロンの間の記号は修飾名です。
DUMPBIN を使用して装飾名を確認するには
OBJ または LIB ファイルにエクスポートされたシンボルを表示するには、開発者コマンド プロンプトで「
dumpbin /exports <obj-or-lib-file>
」と入力します。装飾形式のシンボルを見つけるには、かっこに囲まれた非装飾名を探します。 装飾名は、同じ行の、非装飾名の前にあります。
非装飾名の表示
undname.exe を使用すると、装飾名を非装飾形式に変換できます。 変換の動作を次の例に示します。
C:\>undname ?func1@a@@AAEXH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.
Undecoration of :- "?func1@a@@AAEXH@Z"
is :- "private: void __thiscall a::func1(int)"