I want to pass a macro as an argument in a C function, and I don't know if it possible.
I would like to see this operation, for instance:
I have these macros:
#define PRODUCT(A, B) ((A) * (B))
#define SUM(A, B) ((A) + (B))
And then I have this function with the following signature:
int just_a_function(int x, MACRO_AS_PARAMATER_HERE);
and then i want to call this function like:
just_a_function(10, SUM);
is it possible?
Thanks
You can't pass as function argument.
But if function is a macro this is possible.
#include <stdio.h>
#define PRODUCT(A, B) ((A) * (B))
#define SUM(A, B) ((A) + (B))
#define JUST_A_FUNCTION(A, B, MACRO) MACRO(A, B)
int main() {
int value;
value = JUST_A_FUNCTION(10, 10, SUM);
printf("%d\n", value);
value = JUST_A_FUNCTION(10, 10, PRODUCT);
printf("%d\n", value);
return 0;
}
You can't do that.
Use normal functions instead:
int sum(int x, int y)
{
return x+y;
}
//...
just_another_function(10, sum);
Note: just_another_function must accept int (*)(int, int) as the second argument.
typedef int (*TwoArgsFunction)(int, int);
int just_another_function(int x, TwoArgsFunction fun);
Hi what you are passing is macro means its a substitution your passing . Think about it ..
Ex : #define HIGH 1
In a function you can use int variable. So you can pass 1 to the function . In a function its stored as integer variable
Preprocessor directive works first . Once in a main macro are replaced means in the sense in a function you have to take care of the substitution. If I would have used Macro High 1 ,, in function I will take as int as a argument to get for local function stack. For better understanding check the topics 1.preprocessor directive 2. How the hex file created once you will compile
#include <stdio.h>
#define HIGH 1
#define LOW 0
void pin(int, int);
void pin(int a, int b) {
printf("A: %d B: %d\n", a, b);
}
int main() {
pin(1, HIGH);
return 0;
}
Compilation step involve:
pre processor directive
compiler
linker
executable file
Related
I am writing a generic function which will take macro name and execute correct function.
I am writing a function which will take function name from macro and concatenate this and execute the function.I am adding this header file in my workspace where more than one c file use this macro implementation logic to execute my code.But I am getting error while running the code .
#define STR(name) #name
int convert_f14u18(int a,int b);
int convert_f14s18(int a,int b);
#define VAL_F 14
#define DATA_SIGN u
#define VAL_NUM 18
#define EXECUTE_FUN_NAME(a,b,c,d,e) a##b##c##d##e
#define EXECUTE_STATEMENT(a,b,c,d,e,f) b##c##d##e#f=EXECUTE_FUN_NAME(a,b,c,d,e)
typedef int u32;
u32 add_u32(u32 a,u32 b);
int main() {
//Testing of string macro
printf(STR(Hello));
int numa = 10;
int numb = 20;
int numc = 30;
//int z1 = EXECUTE_FUN_NAME(convert_,f,14,u,18)(numa,numb);
int z1 = EXECUTE_FUN_NAME(convert_,f,VAL_F,DATA_SIGN,VAL_NUM)(numa,numb);
//int z2 = EXECUTE_FUN_NAME(convert_,f,14,s,18)(numa,numc);
int z2 = EXECUTE_FUN_NAME(convert_,f,VAL_F,DATA_SIGN,VAL_NUM)(numa,numc);
printf("\nz1 %d\n",z1);
printf("z2 %d\n",z2);
return 0;
}
int convert_f14u18(int a,int b){
return (a+b);
}
int convert_f14s18(int a,int b){
return (a+b);
}
u32 add_u32(u32 a,u32 b){
return (a+b);
}
Error:../main.cpp: In function ‘int main()’:
../main.cpp:37:76: error: ‘convert_fVAL_FDATA_SIGNVAL_NUM’ was not declared in this scope
int z1 = EXECUTE_FUN_NAME(convert_,f,VAL_F,DATA_SIGN,VAL_NUM)(numa,numb);
Expected result: If I un-comment the lines above of actual macro statement in main statements and comment the current macro statements, I am able to run the code. But I want to make my code run with the current logic .
When replacing a macro, C first replaces each parameter with its argument. So the argument c is replaced with VAL_F, for example. Then it applies the ## operator, which produces convert_fVAL_FDATA_SIGNVAL_NUM in this example. Then C checks the result for additional macros to substitute. However, at that point, the arguments, such as VAL_F, have been made into a single token with ## and are no longer individual tokens that will be replaced.
To deal with this, use one macro to replace the arguments, then use another macro to apply the ## operator. Change:
#define EXECUTE_FUN_NAME(a,b,c,d,e) a##b##c##d##e
to:
#define EXECUTE_FUN_NAME_HELPER(a, b, c, d, e) a##b##c##d##e
#define EXECUTE_FUN_NAME(a, b, c, d, e) EXECUTE_FUN_NAME_HELPER(a, b, c, d, e)
I have two functions foo1(a,b) & foo2(a,b,c) and a macro
#define add(a,b) foo(a,b)
I need to re-define macro to accomplish,
1.if add() is called with 2 parameters, then call foo1
if add() is called with 3 parameters then call foo2
Im new to the option VA_ARGS. How can I do that
If you just want to distinguish between two functions, the following works:
#define ADD(_1, _2, _3, X, ...) X
#define add(...) ADD(__VA_ARGS__, add3, add2, 0)(__VA_ARGS__)
The auxiliary macro ADD always picks the fourth argument:
add(a, b) --> ADD(a, b, add3, add2, 0) --> add2
add(a, b, c) --> ADD(a, b, c, add3, add2, 0) --> add3
The drawback is that you get quite cryptic error messages when you don't supply two or three arguments to the function.
The advantage over variadic functions is that you get type safety. For example if your functions operate on doubles, you can still say add(1, 2) and the integer arguments will be converted to doubles. And variadic functions require some additional information on the number of actual arguments, so that's not a feasible solution here, unless you specify the number of summands in the function.
Addendum: I've changed the add macro so that it doesn't pass an empty variadic list to ADD. Some compilers allow empty lists, but it isn't standard C.
That usual trick for counting arguments may be adapted for this:
#define ADD_EXPAND(...) \
ADD_EXPAND_(__VA_ARGS__, EXPAND_ADD_FUNCS())
#define ADD_EXPAND_(...) \
EXPAND_ADD_SEL_FUNC(__VA_ARGS__)
#define EXPAND_ADD_SEL_FUNC(first_, second_, third_, func, ...) func
#define EXPAND_ADD_FUNCS() foo2, foo, dummy
#define add(...) ADD_EXPAND(__VA_ARGS__)(__VA_ARGS__)
Once you plow through the boiler plate, it basically just involves placing all the arguments in a line, with the function tokens after them, and seeing which function stands out. That's what EXPAND_ADD_SEL_FUNC does.
You can see it live on coliru.
But I'll reiterate what we told you in comments. This is likely to be a sub-par solution to a proper function. I haven't tested it thoroughly, so breakage is easily possible. Use at your own risk.
If you must use variadic macros, then here is a trick.
#define add(...) _Generic ( &(int[]){__VA_ARGS__}, \
int(*)[2]: add2, \
int(*)[3]: add3) (__VA_ARGS__)
Have the macro create a compound literal array. The size of this array will depend on the number of arguments.
Grab the address of the compound literal, to get an array pointer type.
Let _Generic check which type you got, then call the proper function based on that.
This is 100% standard C and also type safe.
Demo:
#include <stdio.h>
#define add(...) _Generic ( &(int[]){__VA_ARGS__}, \
int(*)[2]: add2, \
int(*)[3]: add3) (__VA_ARGS__)
int add2 (int a, int b);
int add3 (int a, int b, int c);
int main (void)
{
printf("%d\n", add(1, 2));
printf("%d\n", add(1, 2, 3));
//printf("%d\n", add(1, 2, 3, 4)); Compiler error for this.
}
int add2 (int a, int b)
{
return a + b;
}
int add3 (int a, int b, int c)
{
return a + b + c;
}
Yesterday I tried to optimize my code using macro, but it doesn't compile in some sentences. For simplification, I writed codes below to describe what I want to work out:
#define MACRO(x, y) ((x) + (y))
#define X 2,3
int fun(x, y)
{
return x+y;
}
int main(void)
{
int res;
res = fun(X); //ok
res = MACRO(X); //**error:macro "MACRO" requires 2 arguments, but only 1 given**
printf("%d\n", res);
return 0;
}
I used to believe that macros simply replace words so it's no problem to do this, but now I think I was wrong. :(
More accurately: I was tring to do something like:
//global.h
#define MACRO(brief, num) fun(__LINE__, brief, num)
//test.c
#include <global.h>
#define X "brief",3
void fun(int line_num, char* brief, int num)
{
printf("%d, %s,%d\n", line_num, brief, num); //do something
}
int main(void)
{
fun(__LINE__, X); //ok
MACRO("brief",3); //ok
MACRO(X); //error: macro "MACRO" requires 2 arguments, but only 1 given
return 0;
}
So I need to use this type of macro to reduce args.
I searched everywhere yesterday but nothing was found, I hope I could receive answers here. Thanks a lot. :)
(My English is not very good, I wish I had a clear description of my problem.)
You can use the variable arguments facility of the preprocessor, as in the following example (available on IdeOne):
#include <stdio.h>
#define MACRO(...) MACRO_IMPLEMENTATION(__VA_ARGS__)
#define MACRO_IMPLEMENTATION(x,y) ((x)+(y))
#define X 2,3
int main (void) {
printf ("MACRO (X) = %d\n", MACRO (X));
printf ("MACRO (2,3) = %d\n", MACRO (2,3));
return 0;
}
The output is
MACRO (X) = 5
MACRO (2,3) = 5
The definition of MACRO takes a variable number or arguments, which are bound to __VA_ARGS__ (see section 6.10.3 in the standard). The definition of MACRO calls MACRO_IMPLEMENTATION which now sees two arguments either because MACRO was called with two or because it was called with an argument which expands to a list of two arguments.
I have a function in my program that takes 3 arguments. Some times in the code there is a macro defining 2 of these parameters.
So this:
void func(int x, int y, int z){...}
Can be invoked like this:
#define PAR 10,20
int z = 3;
func(PAR, z);
Now, I need to change my code so that the function is called like a macro for another function.
#define func(X,Y,Z) func2(X,Y,Z,#Z)
This works fine if X and Y are really passed as variables. Is there any way to make it work also with the macro PAR?
I'm using GCC 4.6
You can do this with an extra level of indirection, (ab)using variadic
macros:
#include <stdio.h>
#define PAR 2,3
#define F(...) G(__VA_ARGS__)
#define G(a,b,c) H(a,b,c)
void H(int a, int b, int c) {
printf("%d %d %d\n", a , b, c);
}
int main() {
F(PAR, 42);
return 0;
}
There is probably a better solution for the underlying problem.
No, I don't believe so. When you define
#define func(X,Y,Z) func2(X,Y,Z,#Z)
You're defining a function-like macro. func(X,Y,Z) actually takes three arguments - and it has to take three arguments. Remember, the preprocessor and not the compiler is interpreting func(PAR, Z).
I've struggled to find any documentation, but it makes sense that the first thing the preprocessor will do (considering that func() is the outer element) is to check to see if the arguments to func() are valid. Then it will place the arguments into func2() and will then expand any macros that were passed as arguments. The code I placed below seems to back up this claim.
Following this logic, the preprocessor will see that func(PAR, Z) isn't a valid call because an argument is missing, which will then throw the error
13:12: error: macro "func" requires 3 arguments, but only 2 given
func(X, Y, Z) will work so long as X and Y are valid macros or variables.
Code (this will give you warnings because there is no function declaration, but the output will be "3 14 3" as expected):
#include <stdio.h>
#include <stdlib.h>
#define PAR 10,20
#define MAR 3
#define WAR 14
#define func(X,Y,Z) print(X, Y, Z)
int Z = 3;
int main(void){
func(MAR,WAR,Z);
return 0;
}
void print(int x, int y, int c){
printf("%d %d %d\n", x, y, c);
}
Out of curiosity, why are you doing this (I don't have enough reputation to comment yet FYI).
I have a call to a function foo(a,b,c) in a C file which I want to prepend with some code. Can I do this with macro? Basically, I want to do the following:
Replace
add(a,b,c)
by
foo()
add(a,b,c)
Is it possible to achieve this with macro?
#include <stdio.h>
int add(int a, int b, int c) {
return a + b + c;
}
void foo() {
printf("Foo!\n");
}
int add2(int a, int b, int c) {
foo();
return add(a, b, c);
}
#define add(a, b, c) add2((a), (b), (c))
int main() {
printf("%d\n", add(5, 3, 1));
return 0;
}
As macros don't expand recursively, the following is possible:
#define add(a, b, c) ( foo() , add((a), (b), (c)) )
The add in the replacement refers to the function, not the macro. This approach, however, has a few pitfalls: Taking the address and using a function pointer will refer to the real function, not the macro, as would enclosing add in parentheses as in (add)(a, b, c).
Sure you can define a macro
#define foo(a,b,c) {foo(); add(a,b,c);}
If C++ inline function is not an option then use comma operator:
#define bar(a, b, c) (foo(), add((a), (b), (c)))