5

I searched far and wide and information on the net seems to suggest that conditional compilation using the preprocessor works exclusively on environment variables.

Basically, I would like to have an inline function or macro perform different operations based in its input arguments. Example of what I want to achieve:

inline void foo(int x) { #if (x < 32) register0 |= (1 << x); #else register1 |= (1 << (x - 32)); #endif } 

The main goal here is that the resulting inline code will not contain conditional code for constant inputs.

Basically, I currently program for a microcontroller (lpc213x) and would like to have an inline function or macro to do pin configuration setup. Since pin configurations are split across multiple registers (e.g. 0 and 1 above), I would like to perform some conditional checks to decide which register is supposed to be written to for a given pin constant.

However, the pin configurations are all constant at compile time, so I would like to eliminate the conditional checks from compile code. I know that optimization would likely get rid of unnecessary conditionals anyway, but I'm wondering whether there is a way to achieve this behavior explicitly, because I might need to disable optimization in the future.

Thanks,

FRob

4
  • 5
    If you are using C++ you can solve this using templates. Don't tag your question C and C++ unless you really have an issue that concerns both of these languages. Commented Nov 29, 2011 at 10:56
  • 4
    Enable optimization in your compiler and it will magically do this for you. Or use constexpr in C++. Commented Nov 29, 2011 at 11:04
  • That should probably be x < 32, not x <= 32 (and the 1 should probably be 1U). Commented Nov 29, 2011 at 11:49
  • Sorry, I tagged it C++ because I thought it concerned the C++ preprocessor as well. Untagged C++ as per your suggestion. Commented Nov 29, 2011 at 11:55

6 Answers 6

6

With C++, you could use template functions, like this:

template <bool B> void doSetRegister(int x); template<> inline void doSetRegister<true>(int x) { register0 |= (1 << x); } template<> inline void doSetRegister<false>(int x) { register1 |= (1 << (x - 32)); } template <int X> inline void setRegister() { doSetRegister<X <= 32>(X); } int main() { setRegister<1>(); setRegister<33>(); } 
Sign up to request clarification or add additional context in comments.

Comments

4

Here's an ugly way for C:

#include <stdio.h> volatile unsigned long register0 = 0, register1 = 0; #define DEF0X(_X_) \ static inline void SetPin##_X_() { register0 |= 1ul << _X_; } #define DEF1X(_X_) \ static inline void SetPin##_X_() { register1 |= 1ul << (_X_ - 32); } DEF0X(0) DEF0X(1) DEF0X(2) DEF0X(3) DEF0X(4) DEF0X(5) DEF0X(6) DEF0X(7) DEF0X(8) DEF0X(9) DEF0X(10) DEF0X(11) DEF0X(12) DEF0X(13) DEF0X(14) DEF0X(15) DEF0X(16) DEF0X(17) DEF0X(18) DEF0X(19) DEF0X(20) DEF0X(21) DEF0X(22) DEF0X(23) DEF0X(24) DEF0X(25) DEF0X(26) DEF0X(27) DEF0X(28) DEF0X(29) DEF0X(30) DEF0X(31) DEF1X(32) DEF1X(33) DEF1X(34) DEF1X(35) DEF1X(36) DEF1X(37) DEF1X(38) DEF1X(39) DEF1X(40) DEF1X(41) DEF1X(42) DEF1X(43) DEF1X(44) DEF1X(45) DEF1X(46) DEF1X(47) DEF1X(48) DEF1X(49) DEF1X(50) DEF1X(51) DEF1X(52) DEF1X(53) DEF1X(54) DEF1X(55) DEF1X(56) DEF1X(57) DEF1X(58) DEF1X(59) DEF1X(60) DEF1X(61) DEF1X(62) DEF1X(63) #define SET_PIN(_X_) SetPin##_X_() int main(void) { SET_PIN(0); SET_PIN(1); SET_PIN(32); SET_PIN(63); printf("register0=0x%08lX register1=0x%08lX\n", register0, register1); return 0; } 

Output:

register0=0x00000003 register1=0x80000001 

1 Comment

So it is possible :D While I agree that this is somewhat unsightly, I think the overall functionality using a combined SET_PIN function is great :D Thanks!
2

And if you are coding in C, only thing you can do is to define two versions of foo().

Comments

2

You can remove conditional code by using short-circuit evaluation trick:

void foo(int x) { x < 32 && (register0 |= (1 << x)); x >= 32 && (register1 |= (1 << (x - 32))); } 

Comments

1

try this

#define X 15 // or some else #if X <= 32 # define SET_X register0 |= (1 << X) #else # define SET_X register1 |= (1 << (x - 32)) #endif 

Comments

0

If you use the C Preprocessor to create a set of defines composed of two unsigned longs and then use these as arguments to your function foo(), the code is pretty straightforward. And if you need to add another register, you can modify the defines.

#define PIN_00 0x00000001, 0x00000000 #define PIN_01 0x00000002, 0x00000000 // defines left out here #define PIN_31 0x80000000, 0x00000000 #define PIN_32 0x00000000, 0x00000001 // defines left out here #define PIN_63 0x00000000, 0x80000000 inline void foo (unsigned long reg1, unsigned long reg2) { register0 |= reg1; register1 |= reg2; } 

Then to use this function foo() you would specify the appropriate define. Since bitwise ORing with zero makes no change, the registers will be updated appropriately.

foo (PIN_00); foo (PIN_01); foo (PIN_32); foo (PIN_63); 

If you needed to add a way to remove bits you can make a new function using the same defines as follows:

inline void fooRemove (unsigned long reg1, unsigned long reg2) { register0 &= ~reg1; register1 &= ~reg2; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.