我尝试使用通过宏生成函数的代码,如下所示:
文件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。
有没有办法使用函数指针 生成函数?
答案 0 :(得分:2)
就像其他任何功能一样,您必须声明它们。这通常在头文件中完成。
您可以直接执行此操作,也可以定义类似于定义功能的宏。
具体而言,将其放在一个头文件中,您在两者中包含您定义函数的文件以及您使用它们的文件中的文件:
extern void MyGeneratedFunctionNo1(void);
答案 1 :(得分: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)
P.S。另外,请注意@James Kanze在评论中提到的一个重要的微妙点(我最初错过了)。 ##
运算符不得用于形成无效的预处理标记。在预处理器中,语法(
是一个单独的独立预处理标记(标点符号),而函数名称也是一个单独的独立预处理标记(标识符)。如果您尝试使用(
运算符强制将函数名称连接到##
,则最终会得到无效的预处理标记和未定义的行为。
不要将(
连接到函数名称。从宏定义中删除第二个##
。没有它,它将按预期工作。