条件编译取决于函数参数?

时间:2011-11-29 10:54:45

标签: c c-preprocessor

我搜索的范围很广,网上的信息似乎暗示使用预处理器的条件编译仅适用于环境变量。

基本上,我希望内联函数或宏基于其输入参数执行不同的操作。我想要实现的例子:

inline void foo(int x) {

    #if (x < 32)

        register0 |= (1 << x);

    #else

        register1 |= (1 << (x - 32));

    #endif

}

这里的主要目标是生成的内联代码不包含常量输入的条件代码。

基本上,我目前正在为微控制器(lpc213x)编程,并希望使用内联函数或宏来进行引脚配置设置。由于引脚配置分为多个寄存器(例如上面的0和1),我想执行一些条件检查来决定应该为给定的引脚常数写入哪个寄存器。

但是,引脚配置在编译时都是常量,所以我想从编译代码中消除条件检查。我知道优化可能会消除不必要的条件,但我想知道是否有办法明确地实现这种行为,因为我可能需要在将来禁用优化。

谢谢,

FROB

6 个答案:

答案 0 :(得分:6)

使用C ++,您可以使用模板函数,如下所示:

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

答案 1 :(得分:3)

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

输出:

register0=0x00000003 register1=0x80000001

答案 2 :(得分:2)

如果您使用C编码,那么您唯一能做的就是定义两个版本的foo()。

答案 3 :(得分:2)

您可以使用short-circuit evaluation技巧删除条件代码:

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

答案 4 :(得分:1)

试试这个

#define X 15 // or some else

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

答案 5 :(得分:0)

如果使用C预处理器创建一组由两个无符号long组成的定义,然后将它们用作函数foo()的参数,则代码非常简单。如果您需要添加另一个寄存器,则可以修改定义。

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

然后使用此函数foo(),您将指定适当的定义。由于零位ORing没有变化,寄存器将被适当更新。

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

如果您需要添加删除位的方法,可以使用相同的定义创建新函数,如下所示:

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