Conditional Preprocessor macro expansion in C - c

I have a macro, SOME_MACRO. It takes an argument.
Definition of SOME_MACRO:
#define SOME_MACRO(arg) __SOME_MACRO(arg)
Further I want __SOME_MACRO(arg) to expand to "ABC" if arg is 0. And if arg is not zero, __SOME_MACRO(arg) should expand to "DEF"
Suppose I call with argument 0, that is: SOME_MACRO(0)
I need to test at preprocessing time, whether the argument is zero or not.
#if <argument is zero> // line 1
#define __SOME_MACRO(arg) "ABC"
#elif
#define __SOME_MACRO(arg) "DEF"
#endif
My question is: What should be at line 1?
Taking an example:
SOME_MACRO(2) should expand to "DEF"
SOME_MACRO(0) should expand to "ABC"

Here is a solution for the requested behavior. Do not use it, it is bad practice, and you should not be attempting this.
/* Define __SOME_MACRO:
Defer is used so that its arguments will be macro-replaced before
Kludge is processed.
"Kludge" is pasted to arg. If this makes "Kludge0", it will be
replaced by two arguments (an empty argument, a comma, and the argument
"abc"). Otherwise, if it forms a single token, that is one argument.
(If the pasting does not form a proper token, the behavior is
undefined. Most likely, the compiler will report an error.)
The resulting argument(s) are then passed to Kludge, followed by "DEF".
Kludge is replaced by its second argument. If __SOME_MACRO's argument
was "0", this second argument is "ABC". Otherwise, it is "DEF".
*/
#define Kludge0 , "ABC"
#define Kludge(x, y,...) y
#define Defer(x, ...) Kludge(x, __VA_ARGS__)
#define __SOME_MACRO(arg) Defer(Kludge##arg, "DEF",)
__SOME_MACRO(0)
__SOME_MACRO(2)

This is not possible. The expression given to #if is only evaluated once, at the line where #if is encountered. There is no way to have it evaluated again each time you invoke your macro.
As Eric Postpischil says, C does not have any general way to make the expansion of a macro conditional on its arguments.
A couple of possible alternatives:
Use an expression with the ternary ?: operator, as pmg suggested in a comment:
#define __SOME_MACRO(arg) ((arg) ? "DEF" : "ABC")
Then SOME_MACRO(0) will expand to ((0) ? "DEF" : "ABC"). Any reasonable compiler will notice that the condition is a constant, and compile this just as if you had only written "ABC"; it should not generate code for a test nor for the unreachable branch. Conditionals with the ternary operator can even be used in expressions that must be compile-time constants, as long as the condition is itself a compile-time constant; e.g. __SOME_MACRO(0) can be used to initialize a global or static variable.
Of course this will not work if the desired expansion is not syntactically an expression, e.g. if you are trying to use your macro to create declarations or definitions or something more syntactically elaborate.
If you know that only a small set of possible arguments will be used, you could use token pasting with the ## operator to expand the macro as one of another set of macros:
#define __SOME_MACRO_0 "ABC"
#define __SOME_MACRO_1 "DEF"
#define __SOME_MACRO_2 "DEF"
#define __SOME_MACRO(arg) __SOME_MACRO_ ## arg
Then __SOME_MACRO(0) expands to "ABC" and __SOME_MACRO(2) expands to "DEF". However __SOME_MACRO(3) will not compile unless you write a corresponding __SOME_MACRO_3 macro, and __SOME_MACRO(0+1) cannot be made to work at all, at least not in any way that I know of.
(As written, __SOME_MACRO(0+1) expands to "ABC"+1, which is equivalent to "BC" and will probably cause you a lot of confusion before you figure out what is wrong. __SOME_MACRO(1-1) is even worse...)
Also, #define ZERO 0 followed by __SOME_MACRO(ZERO) doesn't work as it stands, thought it can be fixed by doing
#define SECOND_MACRO(arg) __SOME_MACRO_ # arg
#define __SOME_MACRO(arg) SECOND_MACRO(arg)

Related

Generalized iteration over arguments of macro in the C preprocessor

There were several questions here regarding variadic macros in C. These include:
How to make a variadic macro (variable number of arguments) which explains the basics, e.g., passing a variable number of arguments to functions such as printf
Is it possible to iterate over arguments in variadic macros?, which explains how to iteratively apply a macro to each of the arguments of the variadic macro.
https://github.com/swansontec/map-macro which explains how to do so on pairs
My question is related to the iteration technique. I am interested in a macro with this generalized semantics.
ITERATE(Before, Action, Between, After, Empty, ...)
that will place Before prior to all expansions, apply Action to each argument, place Between between every two consecutive applications, and will finally place the expansion of After. Moreover, if the number of argument With such a macro, it should be possible to write
// Loop elements
#define A(x) (x)
#define Befor (
#define After )
#define Between ||
#define Empty 1
// Define an OR macro
#define OR(...) ITERATE(Before, A, Between, Empty, __VA_ARGS__)
// Use it
OR() // Expands to 1
OR(a) // Expands to ((a))
OR(a,b) // Expands to ((a)||(b))
OR(a,b,c) // Expands to to ((a)||(b)||(c))
The purpose of course is not to write an OR function. A generalized functionality could be for more intricate applications. E.g., a macro for defining classes and functions, something to print the trace, etc.
I never liked the recursive REPEAT() macro idiom - it generates horrible hour long read error messages that are.. recursive, so you don't know where the error is and it's also hard to grasp how the OBSTRUCT(REPEAT_INDIRECT) () stuff works. Overall, overloading the macro on number of arguments and using an external tool (shell script or m4 preprocessor) to generate C source code is waay easier, easier to read, maintain and fix and also you can expand the macros on the tools side removing the burden of recursive expansion on C side. With that in mind, your ITERATE can be generated with existing preprocessor libraries, P99_FOR or BOOST_FOREACH comes to mind.
Also, typing shift all the time is strange - I prefer snake case. Here's a reduced example without Before and After macros with overloading the macro on number of arguments:
#define _in_ITERATE_0(f,b,e) e()
#define _in_ITERATE_1(f,b,e,_1) f(_1)
#define _in_ITERATE_2(f,b,e,_1,...) f(_1)b()_in_ITERATE_1(f,b,e,__VA_ARGS__)
#define _in_ITERATE_3(f,b,e,_1,...) f(_1)b()_in_ITERATE_2(f,b,e,__VA_ARGS__)
// or you could expand it instead of reusing previous one with same result:
#define _in_ITERATE_4(f,b,e,_1,_2,_3,_4) f(_1)b()f(_2)b()f(_3)b()f(_4)
// etc.... generate
#define _in_ITERATE_N(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) _in_ITERATE_##N
#define ITERATE(func, between, empty, ...) \
_in_ITERATE_N(0,##__VA_ARGS__,9,8,7,6,5,4,3,2,1,0)(func, between, empty, ##__VA_ARGS__)
#define _in_OR_OP(x) (x)
#define _in_OR_EMPTY() 1
#define _in_OR_BETWEEN() ||
#define OR(...) (ITERATE(_in_OR_OP, _in_OR_BETWEEN, _in_OR_EMPTY, ##__VA_ARGS__))
// Use it
OR() // Expands to (1)
OR(a) // Expands to ((a))
OR(a,b) // Expands to ((a)||(b))
OR(a,b,c) // Expands to to ((a)||(b)||(c))
outputs:
(1)
((a))
((a)||(b))
((a)||(b)||(c))
For more examples on overloading macro on count of arguments see this thread. I am using ## GNU extension to remove the comma before __VA_ARGS__ because I am used to using it - I think __VA_OPT__(,) should be nowadays preferred, I am not sure.

Defining C macros in preprocessor if statements

Below I change the value of the function that I call depending on the value of INPUT:
#include <stdio.h>
#define INPUT second
#if INPUT == first
#define FUNCTOCALL(X) first(X)
#elif INPUT == second
#define FUNCTOCALL(X) second(X)
#endif
void first(int x) {
printf("first %d\n", x);
}
void second(int x) {
printf("second %d\n", x);
}
int main() {
FUNCTOCALL(3);
return 0;
}
However, the output is first 3, even if INPUT is equal to second, as above. In fact, the first branch is always entered, regardless of the value of INPUT. I'm completely stumped by this - could someone explain what stupid mistake I'm making?
The c preprocessor only works on integer constant expressions in its conditionals.
If you give it tokens it can't expand (such as first or second where first and second aren't macros)
it'll treat them as 0 and 0 == 0 was true last time I used math. That's why the first branch is always taken.
6.10.1p4:
... After all replacements due to macro expansion and the defined
unary operator have been performed, all remaining identifiers
(including those lexically identical to keywords) are replaced with
the pp-number 0, and then each preprocessing token is converted into a
token. ...
You have no macros first and second defined. Be aware that the pre-processor is not aware of C or C++ function names!* In comparisons and calculations (e. g. #if value or #if 2*X == Y), macros not defined (not defined at all or undefined again) or defined without value evaluate to 0. So, as first and second are not defined, INPUT is defined without value, and the comparison in both #if expressions evaluates to 0 == 0...
However, if you did define the two macros as needed, they would collide with the C function names and the pre-processor would replace these with the macro values as you just defined them, most likely resulting in invalid code (e. g. functions named 1 and 2)...
You might try this instead:
#define INPUT SECOND
#define FIRST 1
#define SECOND 2
#if INPUT == FIRST
#define FUNCTOCALL(X) first(X)
#elif INPUT == SECOND
#define FUNCTOCALL(X) second(X)
#else
# error INPUT not defined
#endif
Note the difference in case, making the macro and the function name differ.
* To be more precise, the pre-processor is not aware of any C or C++ tokens, so it does not know about types like int, double, structs or classes, ... – all it knows is what you make it explicitly aware of with #define, everything else is just text it operates on and, if encountering some known text nodes, replacing them with whatever you defined.

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.

C language macro code - #define with 2 '##'

I recently came across this question and could not find supporting document or data in explanation. The question was asked to me and the person was not willing to share the answer.
#define BIT(A) BIT_##A
#define PIN_0 0
"Do we get BIT_0 by using macro BIT(PIN_0)? If no make necessary corrections?"
I dont know the answer to the above question?
The macro
#define BIT(A) BIT_##A
means to create a single token from what would otherwise be two separate tokens. Without using ## (the token concatenation operator), you might be tempted to do one of:
#define BIT(A) BIT_A
#define BIT(A) BIT_ A
The problem with the first is that, because BIT_A is already a single token, no attempt to match the A to the passed argument will succeed, and you'll get the literal expansion BIT_A no matter what you've used as an argument:
BIT(42) -> BIT_A
The problem with the second is that, even though A is a separate token and will therefore be subject to replacement, the final expansion will not be a single token:
BIT(42) -> BIT_ 42
The ## in your macro takes the value specified by A, and appends it to the literal BIT_ forming one token so, for example,
BIT(7) -> BIT_7
BIT(PIN0) -> BIT_PIN0, but see below if you want BIT_0
This is covered in C11 6.10.3.3 The ## operator:
... each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing
token is concatenated with the following preprocessing token.
The resulting token is available for further macro replacement.
Now, if you want a macro that will concatenate together BIT_ and another already-evaluated macro into a single token, you have to use some trickery to get it to do the initial macro substitution before the concatenation.
That's because the standard states that the concatenation is performed before regular macro replacement, which is why this trickery is needed. The problem with what you have:
#define PIN_0 0
#define BIT(A) BIT_##A
is that the ## expansion of BIT(PIN0) will initially result in the single token BIT_PIN0. Now, although that's subject to further macro replacement, that single token doesn't actually have a macro replacement, so it's left as is.
To get around this, you have to use levels of indirection to coerce the preprocessor into doing regular macro replacement before ##:
#define CONCAT(x,y) x ## y
#define PIN0 0
#define BIT(A) CONCAT(BIT_,A)
This series of macros shown above goes through a number of stages:
BIT(PIN0)
-> CONCAT(BIT_,PIN0)
-> CONCAT(BIT_,0)
-> BIT_0

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;
}

Resources