C Macro Arguments including comma - c

I would like to pass 2 arguments to a macro using another macro:
#define A_AND_B 5,1
#define ADD(a, b) a + b
int add_them(void)
{
int result = ADD(A_AND_B);
return result ;
}
I would hope that expands to
int result = 5 + 1;
and I get 6. Instead I get
Error 'ADD' undeclared (first use in this function)
Error macro "ADD" requires 2 arguments, but only 1 given
Is there a way around this?

As is often the case, you need an extra level of (macro) indirection:
#define A_AND_B 5,1
#define ADD(...) ADD_(__VA_ARGS__)
#define ADD_(a, b) a + b
int add_them(void)
{
int result = ADD(A_AND_B);
return result ;
}
ADD is defined as variadic so that it will work as either ADD(A_AND_B) or ADD(A, B).
This works because __VA_ARGS__ in the replacement body of ADD is replaced with the actual arguments before the replacement body is scanned for macros.

Per C 2018 6.10.3.1, a compiler first identifies the arguments for a function-like macro and then performs macro replacement on the arguments, followed by macro replacement for the function-like macro. This means that, in ADD(A_AND_B), the argument is identified as A_AND_B before it is replaced with 5,1. As the macro invocation has only this single argument and the macro is defined to have two parameters, an error is diagnosed.
Given your definition of ADD, there is no way to change this behavior in a compiler that conforms to the C standard.
You can instead use another macro to expand the arguments and apply the desired macro:
#define Apply(Macro, Arguments) Macro(Arguments)
then int result = Apply(ADD, A_AND_B); will work. That will identify ADD and A_AND_B as arguments to Apply. Then it will expand those, producing an unchanged ADD and 5,1. Then the macro replacement for Apply produces ADD(5,1). Then this is again processed for macro replacement, which replaces ADD(5,1) in the ordinary way.
Note that good practice is usually to define ADD as #define ADD(a, b) ((a) + (b)) to avoid unexpected interactions with other operators neighboring the use of the macro.

Related

Use of # in a macro [duplicate]

This question already has answers here:
C preprocessor: stringize macro and identity macro
(2 answers)
What does #x inside a C macro mean?
(4 answers)
How can I concatenate twice with the C preprocessor and expand a macro as in "arg ## _ ## MACRO"?
(3 answers)
Closed 6 years ago.
Please explain the code
#include <stdio.h>
#define A(a,b) a##b
#define B(a) #a
#define C(a) B(a)
main()
{
printf("%s\n",C(A(1,2)));
printf("%s\n",B(A(1,2)));
}
Output
12
A(1,2)
I don't understand, how the first printf evaluates to 12?
Isn't it similar to the second, as C macro is simply a wrapper to B macro?
As mentioned in Wikipedia in C-preprocessor :
The ## operator (known as the "Token Pasting Operator") concatenates
two tokens into one token.
The # operator (known as the "Stringification Operator") converts a
token into a string, escaping any quotes or backslashes appropriately.
If you want to stringify the expansion of a macro argument, you have
to use two levels of macros:
You cannot combine a macro argument with additional text and stringify
it all together. You can however write a series of adjacent string
constants and stringified arguments: the C compiler will then combine
all the adjacent string constants into one long string.
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo) // outputs "foo"
xstr (foo) // outputs "4"
Also, from C-FAQ Question 11.17 :
It turns out that the definition of # says that it's supposed to
stringize a macro argument immediately, without further expanding it
(if the argument happens to be the name of another macro).
So, similarly, going along these lines :
you're doing C(A(1,2)),
which would roll to C(12), // since no #, so inner argument is expanded
and then to B(12)
// [since you've done two levels of macros in the code:
// 1. from C() to B(), and then, 2. B() to #a]
= 12 .
Whereas, in the first case, only 1 level of stringification is plainly done as per definition of B(a)(since it gets stringified immediately because of #)
macro-replacement of B(A(1,2))
= stringification of A(1,2)
= A(1,2).
The confusion here comes from a simple rule.
When evaluating a macro the pre-processor first resolves the macros in the arguments passed to the macro. However, as a special case, if an argument is right of # or adjacent to ##, it doesn't resolve macros within such arguments. Such are the rules.
Your first case
C(A(1,2))
The pre-processor first applies the C(a) macro, which is defined as B(a). There's no # or ## adjacent to the argument in the definition (none of them in B(a) at all), thus the pre-processor must resolve macros in the argument:
A(1,2)
The definition of A(a,b) is a##b which evaluates into 12.
After the macros in the arguments of the C(a) macro are evaluated, the C macro becomes:
C(12)
The pre-processor now resolves the C(a) macro, which according to its definition becomes
B(12)
Once this is done, the pre-processor evaluates macros inside the result once again and applies the B(a) macro, so the result becomes
"12"
Your second case
B(A(1,2))
Similar to the first case, the pre-processor first applies the B(a) macro. But this time, the definition of the macro is such that the argument is preceded by #. Therefore, the special rule applies and macros inside the argument are not evaluated. Therefore, the result immediately becomes:
"A(1,2)"
The preprocessor goes over the result again trying to find more macros to expand, but now everything is a part of the string, and macros don't get expanded within strings. So the final result is:
"A(1,2)"
C preprocessor has two operators # and ##. The # operator turns the argument of a function like macro to a quoted string where ## operator concatenates two identifiers.
#define A(a,b) a##b will concatenate a with b returning ab as string.
so A(1,2) will return 12
#define B(a) #a will return a as string
#define C(a) B(a) will call previous one and return a as string.
so C(A(1,2)) = C(12) = B(12) = 12 (as string)
B(A(1,2)) = A(1,2) because A(1,2) is taken as an argument and returned as string A(1,2)
There are two operators used in the function-like macros:
## causes a macro to concatenate two parameters.
# causes the input to be effectively turned into a string literal.
In A(a,b) ## causes a to be concatenated with b. In B(a), # effectively creates a string literal from the input. So the expansion runs as follows:
C(A(1,2)) -> C(12) -> B(12) -> "12"
B(A(1,2)) -> "A(1,2)"
Because for C(A(1,2)), the A(1,2) part is evaluated first to turn into 12, the two statements aren't equal like they would appear to be.
You can read more about these at cppreference.

Is there a way to force C preprocessor to evaluate macro arguments before the macro

I have a number of macros in the form
#define F(A,B) Some function of A and B
and for readability I would like to define arguments for these macros e.g.
#define C A,B
so that I can say
F(C)
but the preprocessor tries to expand F before C and complains that F needs 2 arguments. Is there a way to make it expand C before it expands F so that the error does not occur?
You can use an intermediate macro that takes a variable number of arguments:
#define F1(A,B)
#define F(...) F1(__VA_ARGS__)
#define C A,B
int main(void) {
F(C)
F(1,2)
return 0;
}
This should compile. You will still get a compilation failure if you pass more or less than two arguments, or arguments that don't expand to exactly two arguments.
Macro expansion (erroneously) does not trigger argument recount. Therefore, any time macro expansion of a function invocation results in a different number of arguments, it must be forced to recount the number of arguments.
Use this pattern to force expansion and recount before invocation:
//Step 1: wrap the entire affected argument pack in parenthesis
#define mFn(A, ExpandingArgument) mFn1((A, ExpandingArgument))
//Step 2: intermediary layer without ## or # is required to actually expand
#define mFn1(...) mFn2(__VA_ARGS__)
//Step3: Paste the parenthesized arguments to final function identifier to trigger
// function like macro interpretation and invocation
#define mFn2(...) mFn3##__VA_ARGS__
//Step4: Implement the actual function as if the standard were written correctly
#define mFn3(A,B,C,...) //Do things

Renaming a macro in C

Let's say I have already defined 9 macros from
ABC_1 to ABC_9
If there is another macro XYZ(num) whose objective is to call one of the ABC_{i} based on the value of num, what is a good way to do this? i.e. XYZ(num) should call/return ABC_num.
This is what the concatenation operator ## is for:
#define XYZ(num) ABC_ ## num
Arguments to macros that use concatenation (and are used with the operator) are evaluated differently, however (they aren't evaluated before being used with ##, to allow name-pasting, only in the rescan pass), so if the number is stored in a second macro (or the result of any kind of expansion, rather than a plain literal) you'll need another layer of evaluation:
#define XYZ(num) XYZ_(num)
#define XYZ_(num) ABC_ ## num
In the comments you say that num should be a variable, not a constant. The preprocessor builds compile-time expressions, not dynamic ones, so a macro isn't really going to be very useful here.
If you really wanted XYZ to have a macro definition, you could use something like this:
#define XYZ(num) ((int[]){ \
0, ABC_1, ABC_2, ABC_3, ABC_4, ABC_5, ABC_6, ABC_7, ABC_8, ABC_9 \
}[num])
Assuming ABC_{i} are defined as int values (at any rate they must all be the same type - this applies to any method of dynamically selecting one of them), this selects one with a dynamic num by building a temporary array and selecting from it.
This has no obvious advantages over a completely non-macro solution, though. (Even if you wanted to use macro metaprogramming to generate the list of names, you could still do that in a function or array definition.)
Yes, that's possible, using concatenation. For example:
#define FOO(x, y) BAR ##x(y)
#define BAR1(y) "hello " #y
#define BAR2(y) int y()
#define BAR3(y) return y
FOO(2, main)
{
puts(FOO(1, world));
FOO(3, 0);
}
This becomes:
int main()
{
puts("hello " "world");
return 0;
}

Macro expansion for macros with arguments vs. variables with the same name

Consider the following C program (ignore the double side-effect issue):
#define max(a, b) (a>b?a:b)
int main(void){
int max = max(5,6);
return max;
}
The GCC preprocessor turns this into:
int main(void){
int max = (5>6?5:6);
return max;
}
Which is quite nice, since you don't have to worry about unintentional collisions between max and max(). The GCC manual says:
A function-like macro is only expanded if its name appears with a pair of parentheses after it. If you write just the name, it is left alone
Is this standardized or just something done by convention?
Yes, the behavior here is well-defined.
Your macro max is a function-like macro (i.e., when you define it, its name is followed immediately by a left parenthesis and it takes arguments).
A use of max later in your code is only an invocation of that macro if the use of max is followed by a left parenthesis. So, these would not invoke the max macro:
int max;
max = 42;
But these would all invoke the max macro:
max(1, 2)
max (1, 2)
max
(
1, 2
)
max()
(Note that the last line is ill-formed because the number of arguments does not match the number of parameters. This is still a macro invocation, though, and would cause a compilation error.)
This behavior is mandated by the C langauge standard. C99 ยง6.10.3/10 states that after a function-like macro has been defined,
Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by the replacement list in the definition (an invocation of the macro).

Concatenation of tokens in variadic macros

In C, is it possible to concatenate each of the variable arguments in a a variadic macro?
Example:
MY_MACRO(A, B, C) // will yield HDR_A, HDR_B, HDR_C
MY_MACRO(X, Y) // will yield HDR_X, HDR_Y
The normal ## operator has special meaning for variadic macros (avoiding the comma for empty argument list). And concatenation when used with __VA_ARGS__ takes place with the first token only.
Example:
#define MY_MACRO(...) HDR_ ## __VA_ARGS__
MY_MACRO(X, Y) // yields HDR_X, Y
Suggestions?
First, the comma rule you are mentioning is a gcc extension, standard C doesn't have it and most probably will never have it since the feature can be achieved by different means.
What you are looking for is meta programming with macros, which is possible, but you'd need some tricks to achieve that. P99 provides you with tools for that:
#define MY_PREFIX(NAME, X, I) P99_PASTE2(NAME, X)
#define MY_MACRO(...) P99_FOR(HDR_, P99_NARG(__VA_ARGS__), P00_SEQ, MY_PREFIX, __VA_ARGS__)
Here MY_PREFIX describes what has to be done with the individual
items.
P00_SEQ declares how the items should be separated
P99_NARGS just counts the number of arguments

Resources