如何在编译期间检查C函数的有效输入?

时间:2012-11-05 18:09:58

标签: c compiler-errors embedded

我正在为微控制器编写嵌入式C代码。代码必须在三个不同的电路板之间共享,输入/输出配置在初始化期间从某些表的运行时设置。

微控制器有24个ADC通道,我有一个功能可以将引脚设置或清除为ADC通道。这意味着函数的输入可以包含0到23(在表中设置),而不是其他任何内容。

我想放置一些预处理器或编译器“东西”,可以识别该函数接收的值不是0-23并抛出某种错误或警告,并防止代码编译以防万一有人放一个表格中的值无效。

有没有人对如何做到这一点有一些建议?

2 个答案:

答案 0 :(得分:3)

在大多数编译器(预处理器)上,您可以使用#error指令。

#define ADC_CHANNEL 34
#if ADC_CHANNEL > 23
#error ADC_CHANNEL exceeds maximum allowed value
#endif

上面会抛出错误,不会编译。

然后使用ADC_CHANNEL作为函数的输入。

或者您可以将ADC_CHANNEL设为enum,并定义ADC_CHANNEL_0 = 0ADC_CHANNEL_1 = 1 ... ADC_CHANNEL_23 = 23。然后让你的函数采用类型ADC_CHANNEL_t,或任何你想要调用的函数,如果使用枚举类型作为参数调用函数,那么将无法使用越界值

示例:

typedef enum {ADC_CHANNEL_0 = 0,
              ADC_CHANNEL_1 = 1,
              ADC_CHANNEL_2 = 2,
              // ...etc...
              ADC_CHANNEL_22 = 22,
              ADC_CHANNEL_23 = 23} adc_channel_t;

void setClearAdcPin(adc_channel_t adcChannel) {
    // ...function body...
}

(从技术上讲,您不需要= 0= 1等,因为编译器会从顺序推断出来。默认情况下enum s从0开始并递增每个值都有1个。但是手动定义每个值更安全,并且允许您执行仅包含您可能使用的3个可能ADC通道的操作,即使它们不是连续的。)

答案 1 :(得分:1)

您可以通过这个肮脏的技巧检查编译器中的范围(而不是预处理器):

const char PIN = 23;
struct check_23 {
    unsigned long bits: PIN+9;
};

如果PIN>这将无法编译23

然后,为了确保您的函数只被赋予编译时常量作为参数,您需要提供宏而不是函数:

#define CONCAT(a, b) a##b
#define MAKESTRUCTNAME(a,b) CONCAT(a,b)

#define PinFunction(PinArg)\
struct MAKESTRUCTNAME(PinCheckStruct, __LINE__) {\
    unsigned long bits: (PinArg)+9;\
};\
RealPinFunction(PinArg);\