1

次のようなマクロを介して関数を生成するコードを使用しようとしています。

ファイルA(提供されたファイルここでは何も変更できません):

#define FUNCTION_GENERATOR(NUM) \
void MyGeneratedFunctionNo##NUM##(void) \
{ \
     another_function_call(NUM); \
} \

FUNCTION_GENERATOR(1)
FUNCTION_GENERATOR(2)
FUNCTION_GENERATOR(3)

ファイルB(ファイルAから生成された関数への関数ポインターを使用したい私のファイル):

typedef void (*function_ptr) (void);
function_ptr func_array[3];
func_array[0] = MyGeneratedFunctionNo1;
func_array[1] = MyGeneratedFunctionNo2;
func_array[2] = MyGeneratedFunctionNo3;
...

当然、コンパイラはMyGeneratedFunctionNo1、MyGeneratedFunctionNo2、MyGeneratedFunctionNo3が定義されていないと文句を言います。

この生成された関数で関数ポインターを使用する方法はありますか?

4

2 に答える 2

2

他の関数と同じように、それらを宣言する必要があります。これは通常、ヘッダーファイルで行われます。

これを直接行うことも、関数を定義するマクロと同様のマクロを定義することもできます

具体的には、これをヘッダーファイルに配置します。ヘッダーファイルは、関数を定義するファイルと、関数を使用するファイルの両方にインクルードします。

extern void MyGeneratedFunctionNo1(void);
于 2013-01-31T15:15:12.057 に答える
2

この問題は、関数ポインタ自体とは何の関係もありません。これらの関数は他の変換ユニットで宣言されていないため、ポインタであるかどうかに関係なく、他の変換ユニットからこれらの関数にアクセスすることはできません。

典型的なマクロベースの手法は、 2つのマクロを提供して使用することを意味します。1つは宣言を生成するためのもので、もう1つは定義を生成するためのものです。

#define FUNCTION_GENERATOR_DECL(NUM) \
void MyGeneratedFunctionNo##NUM(void);

#define FUNCTION_GENERATOR_DEF(NUM) \
void MyGeneratedFunctionNo##NUM(void) \
{ \
     another_function_call(NUM); \
}

その後、いくつかの実装ファイルで「定義」マクロのインスタンス化を使用します(すでに行っているように)

FUNCTION_GENERATOR_DEF(1)
FUNCTION_GENERATOR_DEF(2)
FUNCTION_GENERATOR_DEF(3)

通常、「宣言子」マクロのインスタンス化をヘッダーファイルに配置します。

FUNCTION_GENERATOR_DECL(1)
FUNCTION_GENERATOR_DECL(2)
FUNCTION_GENERATOR_DECL(3)

PSまた、コメントの中で@James Kanzeが言及した重要な微妙な点に注意してください(そして私はinitaillyを見逃しました)。演算子は、##無効な前処理トークンを形成するために使用してはなりません。プリプロセッサの文法(では、別個の独立した前処理トークン(パンクチャ)があり、関数名も別個の独立した前処理トークン(識別子)です。(演算子を使用して関数名をに強制的に連結しようとする##と、無効な前処理トークンと未定義の動作が発生します。

(を関数名に連結しないでください。##マクロ定義から2番目を削除します。それがなくても意図したとおりに機能します。

于 2013-01-31T15:19:47.713 に答える