#pragma weak name1 [= name2] |
weak を使用すると、弱い (weak) 大域シンボルを定義できます。このプラグマは主にソースファイルの中でライブラリを構築するために使用されます。リンカーは弱いシンボルを認識できなくてもエラーメッセージを出しません。
weak プラグマは、次の 2 つの書式でシンボルを指定できます。
文字列書式。文字列は、C++ の変数または関数の符号化された名前でなければいけません。無効な符号化名が指定された場合、その名前を参照したときの動作は予測できません。無効な符号化名を参照した場合、バックエンドがエラーを生成するかどうかは不明です。エラーを生成するかどうかに関わらず、無効な符号化名を参照したときのバックエンドの動作は予測できません。
識別子書式。識別子は、コンパイル単位内であらかじめ宣言された C++ の関数のあいまいでない識別子でなければいけません。識別子書式は変数には使用できません。無効な識別子への参照を検出した場合、フロントエンド (ccfe) はエラーメッセージを生成します。
#pragma weak name という書式の指令は、name を弱い (weak) シンボルに定義します。name のシンボル定義が見つからなくても、リンカーはエラーメッセージを生成しません。また、弱いシンボルの定義を複数見つけた場合でも、リンカーはエラーメッセージを生成しません。リンカーは単に最初に検出した定義を使用します。
プラグマ name の強い定義が存在しない場合、リンカーはシンボルの値を 0 にします。
次の指令は、ping を弱いシンボルに定義しています。ping という名前のシンボルの定義が見つからない場合でも、リンカーはエラーメッセージを生成しません。
#pragma weak ping |
#pragma weak name1 = name2 という書式の指令は、シンボル name1 を name2 への弱い参照として定義します。name1 がどこにも定義されていない場合、name1 の値は name2 の値になります。name1 が別の場所で定義されている場合、リンカーはその定義を使用し、name2 への弱い参照は無視します。次の指令では、bar がプログラムのどこかで定義されている場合、リンカーはすべての参照先を bar に設定します。そうでない場合、リンカーは bar への参照を foo にリンクします。
#pragma weak bar = foo |
識別子書式では、name2 は現在のコンパイル単位内で宣言および定義しなければいけません。たとえば、次のようにします。
extern void bar(int) {...} extern void _bar(int); #pragma weak _bar=bar |
文字列書式を使用する場合、シンボルはあらかじめ宣言されている必要はありません。次の例において、_bar と bar の両方が extern "C" である場合、その関数はあらかじめ宣言されている必要はありません。しかし、bar は同じオブジェクト内で定義されている必要があります。
extern "C" void bar(int) {...} #pragma weak "_bar" = "bar" |
識別子書式を使用するとき、プラグマのあるスコープ中には指定した名前を持つ関数は、1 つしか存在してはいけません。多重定義関数に識別子書式の #pragma weak を使おうとすると、エラーになります。たとえば、次のようにします。
int bar(int); float bar(float); #pragma weak bar // error, ambiguous function name |
このエラーを回避するには、文字列書式を使用します。例を次に示します。
int bar(int); float bar(float); #pragma weak "__1cDbar6Fi_i_" // make float bar(int) weak |
詳細は、Solaris の『リンカーとライブラリ』を参照してください。