Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC Macro with Conditional Expansion?

Tags:

c

gcc

macros

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

like image 622
J-Dizzle Avatar asked Jan 10 '14 00:01

J-Dizzle


People also ask

What is conditional macro expansion?

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.

What does ## mean in macro?

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.

What does the '#' symbol do in macro expansion?

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.

How are macros expanded in c?

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 .


2 Answers

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)

like image 163
Mark Lakata Avatar answered Oct 06 '22 07:10

Mark Lakata


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.

like image 34
fgp Avatar answered Oct 06 '22 06:10

fgp