在编译时是否存在计算最大N个整数常量(MACROS)的通用方法 -

时间:2013-12-02 12:50:27

标签: c embedded

我需要在编译时计算最多N个整数常量(MACROS)。

这是一种可能的出路 -

#define C_MAX_2(a, b)                         (((a) > (b)) ? (a) : (b))
#define C_MAX_3(a, b, c)                      C_MAX_2((C_MAX_2((a),(b))), (c))
#define C_MAX_4(a, b, c, d)                   C_MAX_2((C_MAX_2((a),(b))), \
                                                      (C_MAX_2((c),(d))))
#define C_MAX_5(a, b, c, d, e)                C_MAX_2((C_MAX_3((a),(b), (c))), \
                                                      (C_MAX_2((d),(e))))

C中有哪些更好的通用方式?

3 个答案:

答案 0 :(得分:1)

编译器应该在编译期间计算这些值。当然假设a,b,c,d和e都是常数。这是基本的常数传播。

因此,如果这是预期的,那么这是最佳方式 - 在运行时期间没有max计算。

修改 对于调试(非优化)构建也是如此。

答案 1 :(得分:1)

首先,@ egur是对的,

  

在运行期间没有最大计算。

所以你不应该担心表现

更一致(通用)的方式可能是

#define MAX_2(n1, n2) (n1 > n2 ? n1 : n2)
#define MAX_3(n1, n2, n3)         MAX_2(n1, MAX_2(n2, n3))
#define MAX_4(n1, n2, n3, n4)     MAX_2(n1, MAX_3(n2, n3, n4))
#define MAX_5(n1, n2, n3, n4, n5) MAX_2(n1, MAX_4(n2, n3, n4, n5))

答案 2 :(得分:0)

首先,我们定义一个宏来计算传递的参数数量。

#define COUNTARGS(...) GET21ST(__VA_ARGS__,COUNTDOWN())
#define COUNTDOWN() 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define GET21ST(a20,a19,a18,a17,a16,a15,a14,a13,a12,a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a,...) a

然而GET21ST的扩展将在COUNTDOWN之前发生,因此我们需要强制预编译器以不同的顺序对它们进行评估。幸运的是,this answer为我们提供了一个完成这一任务的机制。

#define EVAL(...)  EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__

#define VANISH()
#define OBSTRUCT(...) __VA_ARGS__ VANISH()
#define COUNTDOWN() 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define COUNTARGS(...) EVAL(OBSTRUCT(GET21ST)(__VA_ARGS__,COUNTDOWN()))
#define GET21ST(a20,a19,a18,a17,a16,a15,a14,a13,a12,a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a,...) a

现在我们可以根据参数的数量从列表中自动选择正确的宏。

Todo,我们需要一组宏来选择。

#define MAX_1(n) n
#define MAX_2(a,b) ((a)>(b)?(a):(b))
#define MAX_3(a,...) MAX_2(a,MAX_2(__VA_ARGS__))
#define MAX_4(a,...) MAX_2(a,MAX_3(__VA_ARGS__))
...
#define MAX_20(a,...) MAX_2(a,MAX_19(__VA_ARGS__))

我们还需要一些方法来生成新的宏调用。

#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__

从这里我们可以定义一个通用的MAX宏来调用适当的特定宏。

#define MAX(...) CAT(MAX_,COUNTARGS(__VA_ARGS__))(__VA_ARGS__)

使用-E标记在https://godbolt.org/上进行测试。

此:

MAX(2,3,4,1)

结果:

(2>(3>(4>1?4:1)?3:(4>1?4:1))?2:(3>(4>1?4:1)?3:(4>1?4:1)))

注意

对于那些使用C ++的人来说,这是一个更简单,更安全的宏。

#include <vector>
#include <algorithm>

#define MAX(...) [](auto v)constexpr{      \
        return *std::max_element(v.begin(), \
                                v.end());    \
    }(std::vector<float>{__VA_ARGS__})

甚至更好,只需自己使用algorithm