C++におけるextern "C"の効果とは?名前マングリングの仕組みと使い方を解説
extern "C"は、C++で定義した関数名にC言語のリンケージ(結合規則)を持たせるためのキーワードです。この指定を行うと、コンパイラは関数名に対して「名前マングリング」を行わなくなります。本記事では、まずC++における名前マングリングの仕組みを確認したうえで、extern "C"キーワードの働きと具体的な活用方法を詳しく解説します。
C++の名前マングリングとは
C++には「関数オーバーロード」という機能があり、同じ名前の関数でも、引数の型や引数の数が異なっていれば複数定義できます。なお、戻り値の型はオーバーロードの判別対象にはなりません。
ここで一つの疑問が生じます。オブジェクトコード上では、C++はどのようにしてこれらの同名関数を区別しているのでしょうか?
その答えが、シンボル名へ引数に関する情報を付加するという手法です。この技術は名前マングリング(Name Mangling)と呼ばれます。ただし、C++標準では名前マングリングの方式が標準化されていないため、コンパイラごとに異なる手法が採用されている点には注意が必要です。
名前マングリングの具体例
次の例では、func()というオーバーロードされた関数と、my_function()という別の関数が定義されています。
例
int func(int x) {
return x*x;
}
double func(double x) {
return x*x;
}
void my_function(void) {
int x = func(2); // 整数版
double y = func(2.58); // double版
}
一部のC++コンパイラでは、これらの関数は次のように内部的に変換されます。
例
int __func_i(int x){
return x*x;
}
double __func_d(double x){
return x*x;
}
void __my_function_v(void){
int x = __func_i(2); // 整数
double y = __func_d(2.58); // double
}
このように、引数の型情報が関数名に組み込まれることで、ソースコード上は同名の関数でも、オブジェクトコード上ではそれぞれ異なるシンボルとして扱われていることが分かります。
Cコードとのリンク時に発生する問題
C言語は関数オーバーロードをサポートしていません。そのため、C++からCのコードをリンクする際には、シンボル名が変更されないよう配慮しなければなりません。次のC++コードはエラーになります。
例
int printf(const char *format,...);
main() {
printf("Hello World");
}
出力
undefined reference to `printf(char const*, ...)' ld returned 1 exit status
このエラーが発生する原因は、printf()という名前がコンパイラによってマングリングされてしまい、リンカが対応する定義を見つけられないことにあります。Cのライブラリ側には、マングリング後の「printf(char const*, ...)」というシンボルは存在せず、元の「printf」という名前しか存在しないためです。
extern "C"による解決策
この問題を解決するには、extern "C"を使用します。このブロック内に記述されたコードについては、C++コンパイラが名前マングリングを行わないことを保証します。つまり、関数名は宣言どおりの形で維持されます。先ほどのコードは、以下のように書き換えることで正しく動作します。
例
extern "C"{
int printf(const char *format,...);
}
main() {
printf("Hello World");
}
出力
Hello World
注意: 上記のコードは、使用するコンパイラや環境によって異なる結果になる場合があります。
まとめ:extern "C"を使う際のポイント
extern "C"は、いわゆるリンケージ指定(linkage specification)の一種であり、C言語と互換性のあるリンケージを明示するために、あらゆるコンパイラで共通して使用できるキーワードです。
利用にあたっては、以下の点にも留意してください。
- リンケージ指定は必ず名前空間スコープ(namespace scope)内に記述する必要があります。
- クラスのメンバ関数はextern "C"の対象外となるため、指定しても無視されます。
- ヘッダファイルをC/C++の双方から使えるようにしたい場合は、__cplusplusマクロによる条件コンパイルと組み合わせるのが一般的なテクニックです。
-
C++のconstキーワードとは?定数宣言の基本とメリットを解説
C++におけるconstは、変数を「定数」として宣言するための型修飾子です。const付きで宣言された変数は、一度初期化するとその値を後から変更することができません。 constを使うメリット constを使用する最大の利点は、プログラム内で値が意図せず書き換えられるのを防げることです。例えば、円周率(PI)のような不変の値を扱う場合、プログラムのどの部分からもその値が変更されないようにしたいはずです。このような値はconstとして宣言しておくことで、誤った代入から守ることができます。 コンパイラの最適化との関係 const修飾された型を持つオブジェクトは、コンパイラによって読み取り専用メ
-
C++学習におすすめの良質なリソース徹底紹介【初心者から中級者まで】
インターネット上には、C++の学習をサポートしてくれる優れたリソースが数多く存在します。ここでは、その中でも特におすすめの教材や学習サイトを厳選してご紹介します。 C++を学ぶための定番リソース一覧 1. cppreference(C++リファレンス) cppreferenceは、C++のほぼすべての基礎〜中級トピックを深く、体系的にカバーしているオンラインリファレンスです。正確で網羅的な情報が揃っており、C++学習者にとってまず押さえておきたい最重要リソースといえるでしょう。辞書代わりに常に手元に置いておくと便利です。 2. 『A Tour of C++』(Bjarne Stroust