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).
Related
I am looking to use the _Generic preprocessor directive to achieve function overloading. I learned to use it from this wonderfully detailed answer.
However, it doesn't seem to cover this case:
#include <stdio.h>
void foo_one(int);
void foo_two(int, float*);
#define FIRST_VARG(_A, ...) _A
#define foo(_X, ...) _Generic( (FIRST_VARG(__VA_ARGS__,)), \
float* : foo_two, \
default : foo_one) (_X, __VA_ARGS__)
void foo_one(int A)
{
printf("FOO ONE: %d\n", A);
}
void foo_two(int A, float* B)
{
printf("FOO TWO: %d, %f", A, *B);
}
void main()
{
float x = 3.14;
float* y = &x;
foo(1); // This statement pops an error
foo(2, y);
}
Here, you can see that the first argument to both functions is an integer. However, the second argument of the second function is a float*. Visual Studio complains about the calling foo(1), but not when calling foo(2, y). The error is
error C2059: syntax error: ')'
I know Visual Studio can support _Generic with a small trick. So, I feel like there is something I am doing wrong. There is a comment in the answer where I learned about _Generic that suggests using (SECOND(0, ##__VA_ARGS__, 0), etc. But I don't understand it.
Can someone walk me through how I could achieve my intended result?
There are two issues. First is selecting the second argument of foo for generic selection in the case when there is no second argument.
Other is #define foo(_X, ...) which will not work for foo(1) because the function macro expect two or more arguments. It often works but it a compiler specific extensions. Compiling in pedantic mode will raise a warning. See https://godbolt.org/z/z7czvGvbc
A related issue is expanding to (_X, __VA_ARGS__)which will not work for foo(1) where ... maps to nothing.
The both issues can be addressed with placing a dummy type (NoArg) at the end of the list prior to extracting the second argument. It will both extend the list and add a value that can be used by _Generic to correctly dispatch the function expression.
#include <stdio.h>
void foo_one(int);
void foo_two(int, float*);
typedef struct { int _; } NoArg;
// use compound literal to form a dummy value for _Generic, only its type matters
#define NO_ARG ((const NoArg){0})
#define foo_(args, a, b, ...) \
_Generic((b) \
,NoArg: foo_one \
,default: foo_two \
) args
// pass copy of args as the first argument
// add NO_ARG value, only its type matters
// add dummy `~` argument to ensure that `...` in `foo_` catches something
#define foo(...) foo_((__VA_ARGS__), __VA_ARGS__, NO_ARG, ~)
void foo_one(int A)
{
printf("FOO ONE: %d\n", A);
}
void foo_two(int A, float* B)
{
printf("FOO TWO: %d, %f\n", A, B ? *B : 42.0f);
}
#define TEST 123
int main(void)
{
float x = 3.14;
float* y = &x;
foo(1); // This statement pops an error
foo(2, y);
foo(TEST, NULL);
return 0;
}
The last issue is addressed by passing a tuple with original arguments as extra argument to foo_ macro, this argument is later passed to the call operator of expression selected by _Generic.
This solution works with all major C17 compilers (gcc, clang, icc, msvc).
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 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
Is it possible to write a preprocessor macro such that would transform a variable number of arguments into successive function calls, such as
MAP(f, 1, 2, 3, ..., n)
into
f(1); f(2); f(3); ... f(n);
So far, I've got following, which seems to work:
#define MAP(f, t, ...) \
{\
t __varlist[] = {__VA_ARGS__};\
for(int i = 0; i < sizeof(__varlist) / sizeof(t); i++)\
f(__varlist[i]);\
}
Note that this macro takes a type parameter so that it can be a bit more useful.
Is there a way to do it without declaring a temporary? Or does it not matter, because the compiler is so smart that it figures out everything? I'm kind of new to C.
use boost.
note:limit size 256. BOOST_PP_LIMIT_SEQ
#include <stdio.h>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/tuple/to_seq.hpp>
#define PROC(r, f, elem) f(elem);
//#define MAP(f, ...) BOOST_PP_SEQ_FOR_EACH(PROC, f, BOOST_PP_TUPLE_TO_SEQ(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)),(__VA_ARGS__)))
#define MAP(f, ...) BOOST_PP_SEQ_FOR_EACH(PROC, f, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__)))
void f(int data){
printf("%d\n", data);
}
int main(){
MAP(f, 1, 2, 3);
return 0;
}
In gcc, you can avoid the type with typeof:
#define MAP(f, a1, ...) \
{\
typeof(a1) __varlist[] = {a1, __VA_ARGS__};\
for(int i = 0; i < sizeof(__varlist) / sizeof(t); i++)\
f(__varlist[i]);\
}
Doing it without a temporary, i.e. really building N calls if there are N parameters, is possible, but rather complicated, and will be limited to some maximum (to support up to N, you'll need to define N macros).
To do this, you'll need a macro that counts its arguments (search this site), and use this number, plus concatenation, to choose one of N macros (e.g. MAP1(f, a), MAP2(f, a, b) and so on).