Home > Net >  Make simple calculations with C pre-processor
Make simple calculations with C pre-processor

Time:10-28

In my C application I configure some features in this way:

#define LED_SIZE        113
#define SEGMENT_SIZE    3

const int LED_SEGMENTS[SEGMENT_SIZE] = {30, 70, 13};

I would like to check if the sum of the literal values are equal to LED_SIZE:

30 70 13 = 113

I'm interested to do this at compile time, using a pre-processor directives. If the sum is not correct it should not compile.

CodePudding user response:

you can use static_assert

#define LED_SIZE        113
#define SEGMENT_SIZE    3

constexpr int LED_SEGMENTS[SEGMENT_SIZE] = {30, 70, 13}; // this need to be constexpr

#include <numeric>

static_assert(
    std::accumulate(LED_SEGMENTS,LED_SEGMENTS SEGMENT_SIZE,0) == LED_SIZE
);

note: std::accumulate is constexpr only since c 20, you may need to write a custom one for earlier standard.

CodePudding user response:

Avoid the C pre-processor.

#include <array>
#include <numeric>
constexpr int LED_SIZE = 113;
constexpr int SEGMENT_SIZE = 3;
constexpr std::array<int, SEGMENT_SIZE> values{30, 70, 13};
static_assert(std::accumulate(values.begin(), values.end(), 0) == LED_SIZE);

CodePudding user response:

using a pre-processor directives

It is not possible to access arrays using preprocessor directives. LED_SEGMENTS[0] means literally LED_SEGMENTS[0] for preprocessor, there is no array access in preprocessor.

You could stay with it in preprocessor world, and then write a variadic overloaded argument macro to calculate the sum of the comma separated list:

#define LED_SIZE        113
#define SEGMENT_SIZE    3

#define LED_SEGMENTS    30, 70, 13

#define SUM_1(a)  a
#define SUM_2(a, ...)  a   SUM_1(__VA_ARGS__)
#define SUM_3(a, ...)  a   SUM_2(__VA_ARGS__)
#define SUM_4(a, ...)  a   SUM_3(__VA_ARGS__)
#define SUM_N(_4,_3,_2,_1,N,...)  SUM##N
#define SUM_IN(...)  SUM_N(__VA_ARGS__,_4,_3,_2,_1)(__VA_ARGS__)
#define SUM(...)  SUM_IN(__VA_ARGS__)

#if SUM(LED_SEGMENTS) != LED_SIZE
#error "SUM(LED_SEGMENTS) != LED_SIZE"
#endif

to do this at compile time

You should use:

#include <functional>
#include <numeric>
#define LED_SIZE        113
#define SEGMENT_SIZE    3

constexpr int LED_SEGMENTS[SEGMENT_SIZE] = {30, 70, 13};
static_assert(std::accumulate(std::begin(LED_SEGMENTS), std::end(LED_SEGMENTS), 0) == LED_SIZE);

CodePudding user response:

You can use the #if preprocessor directive:

#define LED_SIZE        113
#define SEGMENT_SIZE    3

const int LED_SEGMENTS[SEGMENT_SIZE] = {30, 70, 13};

#if (LED_SEGMENTS[0]   LED_SEGMENTS[1]   LED_SEGMENTS[2] != LED_SIZE)
#error "sum of LED segments is not equal the total LED size"
#endif

(untested)

  • Related