Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I check a C function for valid input during compile time?

I am writing embedded C code for a microcontroller. The code has to be shared between three different circuit boards, and the input/output configurations are set at run time from some tables during initialization.

The microcontroller has 24 ADC channels, and I have a function that can either set or clear a pin as an ADC channel. This means that an input to the function can consist of 0 to 23 (which is set in the table) and nothing else.

I would like to put some kind of preprocessor or compiler "thing" that could identify that the function received a value other than 0-23 and throw some kind of error or warning and prevent the code from compiling in case someone put an invalid value in the table.

Does anyone have some advice on how best to do this?

like image 699
Adam Avatar asked Nov 05 '12 18:11

Adam


People also ask

What is used for a function to execute at compile time?

In computing, compile-time function execution (or compile time function evaluation, or general constant expressions) is the ability of a compiler, that would normally compile a function to machine code and execute it at run time, to execute the function at compile time.

What is compile time checking?

Compile-time checking occurs during the compile time. Compile time errors are error occurred due to typing mistake, if we do not follow the proper syntax and semantics of any programming language then compile time errors are thrown by the compiler.

What happens during compile time in C?

Compile time is the period when the programming code (such as C#, Java, C, Python) is converted to the machine code (i.e. binary code). Runtime is the period of time when a program is running and generally occurs after compile time.

Which code is generated during compile time?

Absolute code is generated when it is known at compile time where the process resides in memory.


1 Answers

On most compilers (preprocessors) you can use the #error directive.

I.e.

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

The above would throw an error, and would not compile.

Then use ADC_CHANNEL as the input to your function.

Or you can make ADC_CHANNEL an enum, and define ADC_CHANNEL_0 = 0, ADC_CHANNEL_1 = 1 ... ADC_CHANNEL_23 = 23. Then make your function take type ADC_CHANNEL_t, or whatever you want to call it, and that way if the function is called using the enumerated type as the argument, there will be no way to use an out-of-bounds value.

Example:

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...
}

(You don't technically need the = 0, = 1, etc., since the compiler will infer that from the order. By default enums start at 0 and increment by 1 for each value. But defining each value manually is safer, and lets you do things like only include the 3 possible ADC channels that you might possibly use, even if they aren't consecutive.)

like image 107
llakais Avatar answered Nov 04 '22 17:11

llakais