This question already has answers here:
How to compare strings in C conditional preprocessor-directives
(14 answers)
Closed 2 years ago.
The following structure for C preprocessor directive #if works well.
#define C 1
#if C==1
...
#endif
But I'd like to use something like this:
#define REAL double
#if REAL==double
...
#elif REAL==float
...
#else
assert(0);
#endif
It's not valid. Is there a solution?
Is there a solution?
There is a whole world of ways you can combine macro expansion with conditional compilation. It's unclear which of them you would consider a solution, but here's a possibility:
#define doubledouble 1
#define floatfloat 1
#define concat_literal(x,y) x ## y
#define realtype(t1,t2) concat_literal(t1,t2)
// ...
#define REAL float
#if realtype(REAL, double)
// REAL is double
#elif realtype(REAL, float)
// REAL is float
#else
// REAL is something else
#endif
The realtype macro works by macro-expanding its arguments and concatenating them together. On rescan, if the result is doubledouble or floatfloat then that is expanded further to 1. If it is an identifier that is not defined as a macro name, then the #if treats it as 0.
It's not foolproof, of course. It does not work if REAL has a multi-token expansion, such as long double. There's also a minor risk of collision with other defined macro names.
Related
I'm having a 20yo legacy code (pure C) which defines:
#define X float
before first function and before another function:
#undefine X
#define X double
I'm writing a code which is supposed to work with both definitions (and it'll be copied into both functions automatically). But it's impossible to make such code in a few cases. For these cases I need to detect if my X is float or double and use #if #else #endif.
The #if (X == float) is resolved as 0 == 0 and won't work.
In theory I can grab into legacy code and modify these definition to make my life easier, but I wonder if there is any macro magic which would allow me to workaround this without touching the legacy? Something with conversion X to string may be? Any ideas?
Concatenate with prefix that expands to something you can control.
#define PREFIX_float 0
#define PREFIX_double 1
#define CONCAT(a, b) a##b
#define XCONCAT(a, b) CONCAT(a, b)
#if XCONCAT(PREFIX_, X) == PREFIX_float
This question already has answers here:
How to force macro to not expand
(1 answer)
Pre-processor: Expand a macro only once
(3 answers)
C: is it possible to expand marcos before pasting, but not recursively?
(1 answer)
Closed 9 months ago.
Given macro definitions like this:
#define GPIOA ((1234)+42)
#define GPIOB ((1234)+84)
#define LEDA_GPIO_Port GPIOA
#define LEDB_GPIO_Port GPIOB
#define MY_PORT_GPIOA 0
#define MY_PORT_GPIOB 1
I would like to define a macro MY_PORT which, given LEDA as argument somehow substitutes this to LEDA_GPIO_Port, then to GPIOA, turns that into MY_PORT_GPIOA and this into 0. So MY_PORT(LEDA) should evaluate to 0 and MY_PORT(LEDB) to 1. If the macros GPIOA/GPIOB wouldn't exist, this would be easy, but since they are defined as complex expressions (starting with parentheses) only one substitution must be performed, and the occurence of GPIOA must not be substituted by that expression.
I tried
#define MY_PORT2(port) MY_PORT_##port
#define MY_PORT(name) MY_PORT2(name##_GPIO_Port)
but here MY_PORT(LEDA) returns MY_PORT_LEDA_GPIO_Port, i.e. it lacks one substituion.
#define CONCAT(a,b) a##b
#define MY_PORT2(port) CONCAT(MY_PORT,port)
#define MY_PORT(name) MY_PORT2(name##_GPIO_Port)
does not compile, as it tries to concatenate the definition for GPIOA, i.e. one subtitution too many.
Is it even possible to do exactly one subtitution?
This question already has answers here:
How can I concatenate twice with the C preprocessor and expand a macro as in "arg ## _ ## MACRO"?
(3 answers)
Closed 4 years ago.
I have something like :
#define NBR 42
#define THE_ANS_IS theAnsIsNBR
Currently the second macro is expand as 'theAnsIsNBR' as expected, but i want it to be expand as 'theAnsIs42' i am not sure if it is even possible !?
#define Paste(x, y) x##y
#define Expand(x, y) Paste(x, y)
#define NBR 42
#define THE_ANS_IS Expand(theAnsIs, NBR)
#define _CONCAT(x,y) x ## y
#define CONCAT(x,y) _CONCAT(x,y)
#define NBR 42
#define THE_ANS_IS CONCAT(theAnsIs, NBR)
This works because ## concatenates two tokens. The problem is, they aren't expanded first. But calling another macro on them expands them, therefore you need to nest two function-like macros here.
Macro to replace undefined tokens with some predefined value.
I would like to have some EXPAND(x) macro that will expand to x if x is defined and to, for example, -1 if it is not, so that this code:
#define M1 1
#define M2 2
#undef M3
#define M4 (2*2)
printf("%i %i %i %i", EXPAND(M1), EXPAND(M2), EXPAND(M3), EXPAND(M4));
would print:
1 2 -1 4
Is that possible in C? Only thing that I can think of is to stringify x and then parse it with constexpr function, but that will work only in simple cases.
The only way to do this would be to use some header file that knows all possible macros and checks if they are defined. If not, replace them with -1.
#ifndef M1
#define M1 -1
#endif
#ifndef M2
#define M2 -1
#endif
...
You would then include this header after the file containing the macros/after the macro defines.
Though please note that this is a bad design, full of tight coupling and other incredibly bad ideas. There's certainly better ways to solve the actual problem, like ensuring that the code won't compile if a certain macro is missing.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C preprocessor and concatenation
I have the macro
#define BUS B
I want to make macro BUS_PORT that expands to PORTB.
I did following:
#define BUS_PORT PORT ## BUS
But BUS_PORT expands to PORTBUS. What I did wrong? How to make it right?
As explained in this answer, you need an extra level of indirection. E.g.
#define BUS B
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define BUS_PORT EVALUATOR(PORT, BUS)