如何在C语言中将宏定义的函数传递给其他函数并调用?
Question
I've defined several function-like macros: square(x), add(a,b), subtract(a,b,c). I want to pass these macros to a function ff so that ff can call them. Here's my sample code:
#define square(x) x*x #define add(a,b) a+b #define subtract(a,b,c) a-b-c #include <stdio.h> int ff(my_func) { //do something useful my_func; //this should call square or add or subtract //do something useful } int main() { printf("Square is %d \n",square(3)); //this works fine printf("Add is %d \n", add(7, 8)); //this works fine printf("Subtract is %d \n", subtract(21, 1, 8)); //this works fine ff(square(10)); //this doesn't work, or it can be ff(add(5, 5)); return 0; }
Is this implementation feasible?
Answer
Short answer: No, this approach won't work—here's why, plus practical fixes to achieve your goal.
First, let's clarify the core issue: Preprocessor macros aren't functions or first-class values—they're just text substitution rules that run before your code even compiles. When you write ff(square(10)), the preprocessor replaces square(10) with 10*10 immediately, so your code becomes ff(100) by the time the compiler sees it. The ff function only gets an integer value, not the "macro itself" to invoke later. Also, your ff function signature is invalid (it doesn't specify the type of my_func), which would throw a compile error even if the macro issue didn't exist.
Here are two solid solutions to get the behavior you want:
1. Use Function Pointers (for runtime flexibility)
Replace your macros with actual functions, then pass pointers to those functions to ff. Since your operations take different numbers of arguments, you'll need to create specialized versions of ff for each argument count:
#include <stdio.h> // Replace macros with type-safe functions int square(int x) { return x * x; } int add(int a, int b) { return a + b; } int subtract(int a, int b, int c) { return a - b - c; } // ff for single-argument functions int ff_single(int (*func)(int), int arg) { // Do pre-processing work here int result = func(arg); printf("ff_single result: %d\n", result); // Do post-processing work here return result; } // ff for two-argument functions int ff_double(int (*func)(int, int), int arg1, int arg2) { int result = func(arg1, arg2); printf("ff_double result: %d\n", result); return result; } int main() { ff_single(square, 10); // Calls square(10) inside ff_single ff_double(add, 5, 5); // Calls add(5,5) inside ff_double return 0; }
2. Use a Wrapper Macro (for compile-time substitution)
If you don't need runtime flexibility (i.e., you know which macro you're passing at compile time), you can create a macro that takes another macro invocation as an argument. This works because macros are expanded during preprocessing:
#define square(x) x*x #define add(a,b) a+b #define subtract(a,b,c) a-b-c #include <stdio.h> #define ff(my_func_call) \ do { \ // Do pre-processing work here \ int result = my_func_call; \ printf("ff result: %d\n", result); \ // Do post-processing work here \ } while(0) int main() { ff(square(10)); // Expands to the code block with square(10) substituted ff(add(5,5)); // Expands with add(5,5) ff(subtract(21,1,8)); // Expands with subtract(21,1,8) return 0; }
The do { ... } while(0) wrapper ensures the macro behaves correctly in all contexts (like after an if statement without braces).
Bonus: Inline Functions (Best of Both Worlds)
If you want the performance of macros (no function call overhead) plus the type safety of functions, use inline functions (C99 and later):
#include <stdio.h> inline int square(int x) { return x*x; } inline int add(int a, int b) { return a+b; } inline int subtract(int a, int b, int c) { return a-b-c; } // Reuse the function pointer approach from solution 1 int ff_single(int (*func)(int), int arg) { int result = func(arg); printf("Result: %d\n", result); return result; } int main() { ff_single(square, 10); return 0; }
Inline functions avoid macro pitfalls (like unexpected operator precedence with expressions square(3+2)—macros would compute 3+2*3+2=11, but inline functions give (3+2)*(3+2)=25).
As a general rule, prefer functions (inline or not) over macros whenever possible—they're safer, easier to debug, and maintain type checking.
内容的提问来源于stack exchange,提问作者Arat

