I am almost certain the answer is 'no'. But I'm stubborn; I would really like to implement this feature, and cycles are important (read: embedded).
Goal:
For this embedded application, I have a clock-configuration-sequence which needs to be inlined. All over the place. I would like to do this with a macro.
Problem
The sequence of execution for clock-configuration changes with the argument 'f' (new clock frequency).
- if (f>10) do A first
- if (f<=10) do A last
- f is a compile time constant.
Example
#define setup_post10(f) doA(f); \
doB(f); \
doC(f)
#define setup_pre10(f) doB(f); \
doC(f); \
doA(f)
Question
How can you encapsulate this with a simple setup(f)? E.g. I would like to:
#define set(f) #if(f>10) \
setup_post10(f) \
#else \
setup_pre10(f) \
#end
But it is invalid to use preprocessor directives (e.g. #if) in a macro definition (as I understand it).
Is there a way to do this? For my application every cycle (and byte of flash) is precious; and I am stubborn; I want this level of abstraction in my code.
Thanks!
-Justin
Most macro processors can also modify the sequence of statements generated for a macro expansion, depending on the arguments supplied in the macro invocation. Conditional Assembly is commonly used to describe this feature. It is also referred to as conditional macro expansion.
The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.
The number-sign or "stringizing" operator (#) converts macro parameters to string literals without expanding the parameter definition. It's used only with macros that take arguments.
A macro is a fragment of code that is given a name. You can define a macro in C using the #define preprocessor directive. Here's an example. Here, when we use c in our program, it is replaced with 299792458 .
If every cycle is precious, you should be coding in assembly. :)
If you trust your C compiler optimizer, then just do this
#define set(f) if((f)>10) setup_post10(f) \
else setup_pre10(f)
If f
is a constant, then the compiler will chose only one of the conditional branches to compile, assuming you have minimal optimization turned on. For example set(11)
should translate directly into a call to setup_post10(11)
Checkout the Boost Preprocessor library (http://www.boost.org/doc/libs/1_55_0/libs/preprocessor/doc/index.html). It includes a way to do such things - in particular, it has BOOST_PP_LESS
.
Though if you're only targetting a particular compiler, it'd probably be easier to just use a function instead of a macro, and force it to be inlined. You could then use a simply if
, and rely on the optimizer to optimize it away for constant arguments. Newer GCC versions even have a way to assert that certain values are compiler-time constants, I think, which would pretty much guarantee that the if
will never actually be emitted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With