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

该问题与函数指针本身无关。您将无法以任何方式从其他翻译单元访问这些函数,无论是否为指针,因为它们未在其他翻译单元中声明。

典型的基于宏的技术意味着提供和使用两个宏:一个用于生成声明,一个用于生成定义

#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 在评论中提到的一个重要的微妙点(我最初错过了)。##运算符不得用于形成无效的预处理令牌。在预处理器语法(中是一个独立的独立预处理标记(punctuator),而函数名也是一个独立的独立预处理标记(identifier)。如果您尝试(使用##运算符将​​函数名称强制连接到 ,您将得到一个无效的预处理标记和未定义的行为。

不要将 连接(到函数名。##从宏定义中删除第二个。没有它,它将按预期工作。

于 2013-01-31T15:19:47.713 回答