是否有可能prevent重复,相同的参数在C宏? [英] Is it possible to prevent duplicate, identical arguments to a macro in C?

查看:85
本文介绍了是否有可能prevent重复,相同的参数在C宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一定的罕见的情况下,它可能是prevent有用的复制参数的宏。

There are certain rare cases, it may be useful to prevent duplicate arguments to a macro.

把这个 ELEM(值...)

要检查是否 A B C

if (ELEM(value, A, B, C)) { .... }

有人可以,意外多次,通过在相同的参数如:

Someone could, by accident passes in the same argument multiple times, eg:

if (ELEM(value, A, B, B)) { .... }

而有效的C,但几乎可以肯定出事了,和不大可能是开发者的预期是什么。

While valid C, but almost certainly an accident, and highly unlikely to be what the developer intended.

...这当然是一个简单的例子,实际的错误情况会比较复杂的。

有没有办法通过重复的论点时,让编译器警告/错误结果?

澄清:


  • 参数都没有的不一定所有常数(他们可以变量也可以混合)。

  • Arguments are not necessarily, all constants (they could be mixed with variables too).

注...


  • 问,因为这是我在一些code最近发现一个实际的错误。结果虽然孤单的限制宏/编译器可以去prevent失误,这可能是早期如果检测宏没有答应。结果的当然,这类错误应该code审查发现...结果然而,错误发生。

这可能需要使用一些GCC /编译器特定扩展,如 __ builtin_constant_p

This may have to use some GCC/compiler specific extensions, such as __builtin_constant_p.

要做到这一点的(这也不是省油的证据,但将有助于避免部分错误)的一种方法,
可以是标识符转换为字符串,然后静电断言如果任何标识符是完全匹配。结果,有明显的缺陷,即不同标识符可以重新present同一恒定值。在相同的标识符也可以写成这样才能不比较,例如: A [0] VS A [0]

One way to do this (which isn't fool proof but would help avoid some mistakes), could be to convert the identifiers to strings, then static-assert if any of the identifiers are exact matches.
Having the obvious drawback that different identifiers may represent the same constant value. The the same identifier could also be written so as to not compare, eg: A[0] vs A[ 0 ].

如果在preprocessor ​​/编译器无法做到这一点很容易,退一步的解决方案可能是做一些基本的静态检查工具。

If the preprocessor/compiler can't do this easily, a fall-back solution may be to do some basic static checking tool.

推荐答案

这方法通过比较标识符和在编译时失败,如果他们不符合我们的要求。

This method works by comparing the identifiers and failing at compile time if they don't meet our requirements.

这不是完全防呆因为2个参数可以有效地相同,但是当转换为他们的字符串标识符不匹配。然而,它会赶上最常见的错误。

It's not entirely fool-proof since 2 arguments may be effectively the same, but not match when converted to their string identifiers. Nevertheless, it will catch most common mistakes.

请注意,尽管本的确实工作的,我不知道我会要提交投产code这一点,因为它依赖于一些相当令人费解的宏和明显减慢编译的(在我自己的测试与海湾合作委员会至少)

Note that while this does work, am not sure I would want to commit this into production code since its relying on some quite convoluted macros and slows compilation noticeably (in my own tests with gcc at least).

链接到单个文件的例子。

例如,输出:

Found!
Strings match? 0
Strings match? 1
Strings match? 0
Strings match? 1

C文件:

#include <stdio.h>

int main(void)
{
    int a = 1;

    int A = 0, B = 1, C = 2, D = 3;

    STATIC_ASSERT(!PP_ID_EQ(FOO, BAR));
    STATIC_ASSERT(UNIQUE(A, B, C, D));
    if (ELEM(a, A, B, C)) printf("Found!\n");

    /* uncomment will fail to compile */
    // STATIC_ASSERT(!PP_ID_EQ(MATCH, MATCH));
    // STATIC_ASSERT(UNIQUE(D, A, B, C, D));
    // if (ELEM(a, A, B, B)) printf("Found!\n");

    printf("Strings match? %d\n", PP_ID_EQ(FOO, BAR));
    printf("Strings match? %d\n", PP_ID_EQ(BAR, BAR));
    printf("Strings match? %d\n", PP_STR_EQ("HELLO", "WORLD"));
    printf("Strings match? %d\n", PP_STR_EQ("WORLD", "WORLD"));
}

C头:

/**
 * Script to generate...
 * \code{.py}
 * MAX = 64
 * for i in range(1, MAX):
 *     if i == 1:
 *         print('#define _PP_STRCMP_%d(a, b)                       ((a)[1] == (b)[1])' % (i,))
 *     else:
 *         print('#define _PP_STRCMP_%d(a, b) _PP_STRCMP_%d(a, b) && ((a)[%d] == (b)[%d])' % (i, i - 1, i, i))
 * \endcode
 */
#define _PP_STRCMP_1(a, b)                       ((a)[1] == (b)[1])
#define _PP_STRCMP_2(a, b) _PP_STRCMP_1(a, b) && ((a)[2] == (b)[2])
#define _PP_STRCMP_3(a, b) _PP_STRCMP_2(a, b) && ((a)[3] == (b)[3])
#define _PP_STRCMP_4(a, b) _PP_STRCMP_3(a, b) && ((a)[4] == (b)[4])
#define _PP_STRCMP_5(a, b) _PP_STRCMP_4(a, b) && ((a)[5] == (b)[5])
#define _PP_STRCMP_6(a, b) _PP_STRCMP_5(a, b) && ((a)[6] == (b)[6])
#define _PP_STRCMP_7(a, b) _PP_STRCMP_6(a, b) && ((a)[7] == (b)[7])
#define _PP_STRCMP_8(a, b) _PP_STRCMP_7(a, b) && ((a)[8] == (b)[8])
#define _PP_STRCMP_9(a, b) _PP_STRCMP_8(a, b) && ((a)[9] == (b)[9])
#define _PP_STRCMP_10(a, b) _PP_STRCMP_9(a, b) && ((a)[10] == (b)[10])
#define _PP_STRCMP_11(a, b) _PP_STRCMP_10(a, b) && ((a)[11] == (b)[11])
#define _PP_STRCMP_12(a, b) _PP_STRCMP_11(a, b) && ((a)[12] == (b)[12])
#define _PP_STRCMP_13(a, b) _PP_STRCMP_12(a, b) && ((a)[13] == (b)[13])
#define _PP_STRCMP_14(a, b) _PP_STRCMP_13(a, b) && ((a)[14] == (b)[14])
#define _PP_STRCMP_15(a, b) _PP_STRCMP_14(a, b) && ((a)[15] == (b)[15])
#define _PP_STRCMP_16(a, b) _PP_STRCMP_15(a, b) && ((a)[16] == (b)[16])
#define _PP_STRCMP_17(a, b) _PP_STRCMP_16(a, b) && ((a)[17] == (b)[17])
#define _PP_STRCMP_18(a, b) _PP_STRCMP_17(a, b) && ((a)[18] == (b)[18])
#define _PP_STRCMP_19(a, b) _PP_STRCMP_18(a, b) && ((a)[19] == (b)[19])
#define _PP_STRCMP_20(a, b) _PP_STRCMP_19(a, b) && ((a)[20] == (b)[20])
#define _PP_STRCMP_21(a, b) _PP_STRCMP_20(a, b) && ((a)[21] == (b)[21])
#define _PP_STRCMP_22(a, b) _PP_STRCMP_21(a, b) && ((a)[22] == (b)[22])
#define _PP_STRCMP_23(a, b) _PP_STRCMP_22(a, b) && ((a)[23] == (b)[23])
#define _PP_STRCMP_24(a, b) _PP_STRCMP_23(a, b) && ((a)[24] == (b)[24])
#define _PP_STRCMP_25(a, b) _PP_STRCMP_24(a, b) && ((a)[25] == (b)[25])
#define _PP_STRCMP_26(a, b) _PP_STRCMP_25(a, b) && ((a)[26] == (b)[26])
#define _PP_STRCMP_27(a, b) _PP_STRCMP_26(a, b) && ((a)[27] == (b)[27])
#define _PP_STRCMP_28(a, b) _PP_STRCMP_27(a, b) && ((a)[28] == (b)[28])
#define _PP_STRCMP_29(a, b) _PP_STRCMP_28(a, b) && ((a)[29] == (b)[29])
#define _PP_STRCMP_30(a, b) _PP_STRCMP_29(a, b) && ((a)[30] == (b)[30])
#define _PP_STRCMP_31(a, b) _PP_STRCMP_30(a, b) && ((a)[31] == (b)[31])
#define _PP_STRCMP_32(a, b) _PP_STRCMP_31(a, b) && ((a)[32] == (b)[32])
#define _PP_STRCMP_33(a, b) _PP_STRCMP_32(a, b) && ((a)[33] == (b)[33])
#define _PP_STRCMP_34(a, b) _PP_STRCMP_33(a, b) && ((a)[34] == (b)[34])
#define _PP_STRCMP_35(a, b) _PP_STRCMP_34(a, b) && ((a)[35] == (b)[35])
#define _PP_STRCMP_36(a, b) _PP_STRCMP_35(a, b) && ((a)[36] == (b)[36])
#define _PP_STRCMP_37(a, b) _PP_STRCMP_36(a, b) && ((a)[37] == (b)[37])
#define _PP_STRCMP_38(a, b) _PP_STRCMP_37(a, b) && ((a)[38] == (b)[38])
#define _PP_STRCMP_39(a, b) _PP_STRCMP_38(a, b) && ((a)[39] == (b)[39])
#define _PP_STRCMP_40(a, b) _PP_STRCMP_39(a, b) && ((a)[40] == (b)[40])
#define _PP_STRCMP_41(a, b) _PP_STRCMP_40(a, b) && ((a)[41] == (b)[41])
#define _PP_STRCMP_42(a, b) _PP_STRCMP_41(a, b) && ((a)[42] == (b)[42])
#define _PP_STRCMP_43(a, b) _PP_STRCMP_42(a, b) && ((a)[43] == (b)[43])
#define _PP_STRCMP_44(a, b) _PP_STRCMP_43(a, b) && ((a)[44] == (b)[44])
#define _PP_STRCMP_45(a, b) _PP_STRCMP_44(a, b) && ((a)[45] == (b)[45])
#define _PP_STRCMP_46(a, b) _PP_STRCMP_45(a, b) && ((a)[46] == (b)[46])
#define _PP_STRCMP_47(a, b) _PP_STRCMP_46(a, b) && ((a)[47] == (b)[47])
#define _PP_STRCMP_48(a, b) _PP_STRCMP_47(a, b) && ((a)[48] == (b)[48])
#define _PP_STRCMP_49(a, b) _PP_STRCMP_48(a, b) && ((a)[49] == (b)[49])
#define _PP_STRCMP_50(a, b) _PP_STRCMP_49(a, b) && ((a)[50] == (b)[50])
#define _PP_STRCMP_51(a, b) _PP_STRCMP_50(a, b) && ((a)[51] == (b)[51])
#define _PP_STRCMP_52(a, b) _PP_STRCMP_51(a, b) && ((a)[52] == (b)[52])
#define _PP_STRCMP_53(a, b) _PP_STRCMP_52(a, b) && ((a)[53] == (b)[53])
#define _PP_STRCMP_54(a, b) _PP_STRCMP_53(a, b) && ((a)[54] == (b)[54])
#define _PP_STRCMP_55(a, b) _PP_STRCMP_54(a, b) && ((a)[55] == (b)[55])
#define _PP_STRCMP_56(a, b) _PP_STRCMP_55(a, b) && ((a)[56] == (b)[56])
#define _PP_STRCMP_57(a, b) _PP_STRCMP_56(a, b) && ((a)[57] == (b)[57])
#define _PP_STRCMP_58(a, b) _PP_STRCMP_57(a, b) && ((a)[58] == (b)[58])
#define _PP_STRCMP_59(a, b) _PP_STRCMP_58(a, b) && ((a)[59] == (b)[59])
#define _PP_STRCMP_60(a, b) _PP_STRCMP_59(a, b) && ((a)[60] == (b)[60])
#define _PP_STRCMP_61(a, b) _PP_STRCMP_60(a, b) && ((a)[61] == (b)[61])
#define _PP_STRCMP_62(a, b) _PP_STRCMP_61(a, b) && ((a)[62] == (b)[62])
#define _PP_STRCMP_63(a, b) _PP_STRCMP_62(a, b) && ((a)[63] == (b)[63])

/**
 * Strings must be constant and NULL terminated.
 *
 * Script to generate...
 * \code{.py}
 * MAX = 64
 * print('#define PP_STR_EQ(a, b) ( \\')
 * print('   (sizeof(int[(sizeof(a) > %d ? -1 : 1)])) && \\' % MAX)
 * print('   (sizeof(a) == sizeof(b)) && \\')
 * print(' (((sizeof(a) == 1)) || \\')
 * for i in range(2, MAX + 1):
 *     print('  ((sizeof(a) == %d) && _PP_STRCMP_%d(a, b)) %s' % (i, i - 1, "|| \\" if i != MAX else "))"))
 * \endcode
 */
#define PP_STR_EQ(a, b) ( \
   (sizeof(int[(sizeof(a) > 64 ? -1 : 1)])) && \
   (sizeof(a) == sizeof(b)) && \
 (((sizeof(a) == 1)) || \
  ((sizeof(a) == 2) && _PP_STRCMP_1(a, b)) || \
  ((sizeof(a) == 3) && _PP_STRCMP_2(a, b)) || \
  ((sizeof(a) == 4) && _PP_STRCMP_3(a, b)) || \
  ((sizeof(a) == 5) && _PP_STRCMP_4(a, b)) || \
  ((sizeof(a) == 6) && _PP_STRCMP_5(a, b)) || \
  ((sizeof(a) == 7) && _PP_STRCMP_6(a, b)) || \
  ((sizeof(a) == 8) && _PP_STRCMP_7(a, b)) || \
  ((sizeof(a) == 9) && _PP_STRCMP_8(a, b)) || \
  ((sizeof(a) == 10) && _PP_STRCMP_9(a, b)) || \
  ((sizeof(a) == 11) && _PP_STRCMP_10(a, b)) || \
  ((sizeof(a) == 12) && _PP_STRCMP_11(a, b)) || \
  ((sizeof(a) == 13) && _PP_STRCMP_12(a, b)) || \
  ((sizeof(a) == 14) && _PP_STRCMP_13(a, b)) || \
  ((sizeof(a) == 15) && _PP_STRCMP_14(a, b)) || \
  ((sizeof(a) == 16) && _PP_STRCMP_15(a, b)) || \
  ((sizeof(a) == 17) && _PP_STRCMP_16(a, b)) || \
  ((sizeof(a) == 18) && _PP_STRCMP_17(a, b)) || \
  ((sizeof(a) == 19) && _PP_STRCMP_18(a, b)) || \
  ((sizeof(a) == 20) && _PP_STRCMP_19(a, b)) || \
  ((sizeof(a) == 21) && _PP_STRCMP_20(a, b)) || \
  ((sizeof(a) == 22) && _PP_STRCMP_21(a, b)) || \
  ((sizeof(a) == 23) && _PP_STRCMP_22(a, b)) || \
  ((sizeof(a) == 24) && _PP_STRCMP_23(a, b)) || \
  ((sizeof(a) == 25) && _PP_STRCMP_24(a, b)) || \
  ((sizeof(a) == 26) && _PP_STRCMP_25(a, b)) || \
  ((sizeof(a) == 27) && _PP_STRCMP_26(a, b)) || \
  ((sizeof(a) == 28) && _PP_STRCMP_27(a, b)) || \
  ((sizeof(a) == 29) && _PP_STRCMP_28(a, b)) || \
  ((sizeof(a) == 30) && _PP_STRCMP_29(a, b)) || \
  ((sizeof(a) == 31) && _PP_STRCMP_30(a, b)) || \
  ((sizeof(a) == 32) && _PP_STRCMP_31(a, b)) || \
  ((sizeof(a) == 33) && _PP_STRCMP_32(a, b)) || \
  ((sizeof(a) == 34) && _PP_STRCMP_33(a, b)) || \
  ((sizeof(a) == 35) && _PP_STRCMP_34(a, b)) || \
  ((sizeof(a) == 36) && _PP_STRCMP_35(a, b)) || \
  ((sizeof(a) == 37) && _PP_STRCMP_36(a, b)) || \
  ((sizeof(a) == 38) && _PP_STRCMP_37(a, b)) || \
  ((sizeof(a) == 39) && _PP_STRCMP_38(a, b)) || \
  ((sizeof(a) == 40) && _PP_STRCMP_39(a, b)) || \
  ((sizeof(a) == 41) && _PP_STRCMP_40(a, b)) || \
  ((sizeof(a) == 42) && _PP_STRCMP_41(a, b)) || \
  ((sizeof(a) == 43) && _PP_STRCMP_42(a, b)) || \
  ((sizeof(a) == 44) && _PP_STRCMP_43(a, b)) || \
  ((sizeof(a) == 45) && _PP_STRCMP_44(a, b)) || \
  ((sizeof(a) == 46) && _PP_STRCMP_45(a, b)) || \
  ((sizeof(a) == 47) && _PP_STRCMP_46(a, b)) || \
  ((sizeof(a) == 48) && _PP_STRCMP_47(a, b)) || \
  ((sizeof(a) == 49) && _PP_STRCMP_48(a, b)) || \
  ((sizeof(a) == 50) && _PP_STRCMP_49(a, b)) || \
  ((sizeof(a) == 51) && _PP_STRCMP_50(a, b)) || \
  ((sizeof(a) == 52) && _PP_STRCMP_51(a, b)) || \
  ((sizeof(a) == 53) && _PP_STRCMP_52(a, b)) || \
  ((sizeof(a) == 54) && _PP_STRCMP_53(a, b)) || \
  ((sizeof(a) == 55) && _PP_STRCMP_54(a, b)) || \
  ((sizeof(a) == 56) && _PP_STRCMP_55(a, b)) || \
  ((sizeof(a) == 57) && _PP_STRCMP_56(a, b)) || \
  ((sizeof(a) == 58) && _PP_STRCMP_57(a, b)) || \
  ((sizeof(a) == 59) && _PP_STRCMP_58(a, b)) || \
  ((sizeof(a) == 60) && _PP_STRCMP_59(a, b)) || \
  ((sizeof(a) == 61) && _PP_STRCMP_60(a, b)) || \
  ((sizeof(a) == 62) && _PP_STRCMP_61(a, b)) || \
  ((sizeof(a) == 63) && _PP_STRCMP_62(a, b)) || \
  ((sizeof(a) == 64) && _PP_STRCMP_63(a, b)) ))


/* -------------------------------------------------------------------- */
#define STRINGIFY_ARG(x) "" #x
#define STRINGIFY_APPEND(a, b) "" a #b
#define STRINGIFY(x) STRINGIFY_APPEND("", x)

#define PP_ID_EQ(a, b) \
    PP_STR_EQ(STRINGIFY(a), STRINGIFY(b))


#define STATIC_ASSERT(expr) \
    ((void)sizeof(int[(expr) ? 1 : -1]))


/* -------------------------------------------------------------------- */
/* varargs macros (keep first so others can use) */
/* --- internal helpers --- */
#define _VA_NARGS_GLUE(x, y) x y
#define _VA_NARGS_RETURN_COUNT(\
    _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10_, _11_, _12_, _13_, _14_, _15_, _16_, \
    _17_, _18_, _19_, _20_, _21_, _22_, _23_, _24_, _25_, _26_, _27_, _28_, _29_, _30_, _31_, _32_, \
    _33_, _34_, _35_, _36_, _37_, _38_, _39_, _40_, _41_, _42_, _43_, _44_, _45_, _46_, _47_, _48_, \
    _49_, _50_, _51_, _52_, _53_, _54_, _55_, _56_, _57_, _58_, _59_, _60_, _61_, _62_, _63_, _64_, \
    count, ...) count
#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args
/* 64 args max */
#define _VA_NARGS_COUNT(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
    64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \
    48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, \
    32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
    16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2, 1, 0))
#define _VA_NARGS_OVERLOAD_MACRO2(name, count) name##count
#define _VA_NARGS_OVERLOAD_MACRO1(name, count) _VA_NARGS_OVERLOAD_MACRO2(name, count)
#define _VA_NARGS_OVERLOAD_MACRO(name,  count) _VA_NARGS_OVERLOAD_MACRO1(name, count)
/* --- expose for re-use --- */
#define VA_NARGS_CALL_OVERLOAD(name, ...) \
    _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, _VA_NARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))


/* -------------------------------------------------------------------- */
/* UNIQUE#(v, ...): are all args unique?
 *
 * Script to generate...
 * \code{.py}
 * for i in range(1, 16):
 *     args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)]
 *     print("#define _VA_UNIQUE%d(%s) \\" % (i + 1, ", ".join(args)))
 *     if i > 1:
 *         expr = ["_VA_UNIQUE%d(%s)" % (i, ", ".join(args[:-1]))]
 *     else:
 *         expr = []
 *     for j in range(len(args) - 1):
 *             expr.append("!PP_ID_EQ(%s, %s)" % (args[j], args[-1]))
 *     print("    (" + " && ".join(expr) + ")")
 * \endcode
 */
#define _VA_UNIQUE2(a0, b0) \
    (!PP_ID_EQ(a0, b0))
#define _VA_UNIQUE3(a0, b0, c0) \
    (_VA_UNIQUE2(a0, b0) && !PP_ID_EQ(a0, c0) && !PP_ID_EQ(b0, c0))
#define _VA_UNIQUE4(a0, b0, c0, d0) \
    (_VA_UNIQUE3(a0, b0, c0) && !PP_ID_EQ(a0, d0) && \
     !PP_ID_EQ(b0, d0) && !PP_ID_EQ(c0, d0))
#define _VA_UNIQUE5(a0, b0, c0, d0, e0) \
    (_VA_UNIQUE4(a0, b0, c0, d0) && !PP_ID_EQ(a0, e0) && \
     !PP_ID_EQ(b0, e0) && !PP_ID_EQ(c0, e0) && !PP_ID_EQ(d0, e0))
#define _VA_UNIQUE6(a0, b0, c0, d0, e0, f0) \
    (_VA_UNIQUE5(a0, b0, c0, d0, e0) && !PP_ID_EQ(a0, f0) && \
     !PP_ID_EQ(b0, f0) && !PP_ID_EQ(c0, f0) && !PP_ID_EQ(d0, f0) && !PP_ID_EQ(e0, f0))
#define _VA_UNIQUE7(a0, b0, c0, d0, e0, f0, g0) \
    (_VA_UNIQUE6(a0, b0, c0, d0, e0, f0) && !PP_ID_EQ(a0, g0) && \
     !PP_ID_EQ(b0, g0) && !PP_ID_EQ(c0, g0) && !PP_ID_EQ(d0, g0) && !PP_ID_EQ(e0, g0) && \
     !PP_ID_EQ(f0, g0))
#define _VA_UNIQUE8(a0, b0, c0, d0, e0, f0, g0, h0) \
    (_VA_UNIQUE7(a0, b0, c0, d0, e0, f0, g0) && !PP_ID_EQ(a0, h0) && \
     !PP_ID_EQ(b0, h0) && !PP_ID_EQ(c0, h0) && !PP_ID_EQ(d0, h0) && !PP_ID_EQ(e0, h0) && \
     !PP_ID_EQ(f0, h0) && !PP_ID_EQ(g0, h0))
#define _VA_UNIQUE9(a0, b0, c0, d0, e0, f0, g0, h0, i0) \
    (_VA_UNIQUE8(a0, b0, c0, d0, e0, f0, g0, h0) && !PP_ID_EQ(a0, i0) && \
     !PP_ID_EQ(b0, i0) && !PP_ID_EQ(c0, i0) && !PP_ID_EQ(d0, i0) && !PP_ID_EQ(e0, i0) && \
     !PP_ID_EQ(f0, i0) && !PP_ID_EQ(g0, i0) && !PP_ID_EQ(h0, i0))
#define _VA_UNIQUE10(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \
    (_VA_UNIQUE9(a0, b0, c0, d0, e0, f0, g0, h0, i0) && !PP_ID_EQ(a0, j0) && \
     !PP_ID_EQ(b0, j0) && !PP_ID_EQ(c0, j0) && !PP_ID_EQ(d0, j0) && !PP_ID_EQ(e0, j0) && \
     !PP_ID_EQ(f0, j0) && !PP_ID_EQ(g0, j0) && !PP_ID_EQ(h0, j0) && !PP_ID_EQ(i0, j0))
#define _VA_UNIQUE11(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \
    (_VA_UNIQUE10(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) && !PP_ID_EQ(a0, k0) && \
     !PP_ID_EQ(b0, k0) && !PP_ID_EQ(c0, k0) && !PP_ID_EQ(d0, k0) && !PP_ID_EQ(e0, k0) && \
     !PP_ID_EQ(f0, k0) && !PP_ID_EQ(g0, k0) && !PP_ID_EQ(h0, k0) && !PP_ID_EQ(i0, k0) && \
     !PP_ID_EQ(j0, k0))
#define _VA_UNIQUE12(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \
    (_VA_UNIQUE11(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) && !PP_ID_EQ(a0, l0) && \
     !PP_ID_EQ(b0, l0) && !PP_ID_EQ(c0, l0) && !PP_ID_EQ(d0, l0) && !PP_ID_EQ(e0, l0) && \
     !PP_ID_EQ(f0, l0) && !PP_ID_EQ(g0, l0) && !PP_ID_EQ(h0, l0) && !PP_ID_EQ(i0, l0) && \
     !PP_ID_EQ(j0, l0) && !PP_ID_EQ(k0, l0))
#define _VA_UNIQUE13(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \
    (_VA_UNIQUE12(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) && !PP_ID_EQ(a0, m0) && \
     !PP_ID_EQ(b0, m0) && !PP_ID_EQ(c0, m0) && !PP_ID_EQ(d0, m0) && !PP_ID_EQ(e0, m0) && \
     !PP_ID_EQ(f0, m0) && !PP_ID_EQ(g0, m0) && !PP_ID_EQ(h0, m0) && !PP_ID_EQ(i0, m0) && \
     !PP_ID_EQ(j0, m0) && !PP_ID_EQ(k0, m0) && !PP_ID_EQ(l0, m0))
#define _VA_UNIQUE14(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \
    (_VA_UNIQUE13(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) && !PP_ID_EQ(a0, n0) && \
     !PP_ID_EQ(b0, n0) && !PP_ID_EQ(c0, n0) && !PP_ID_EQ(d0, n0) && !PP_ID_EQ(e0, n0) && \
     !PP_ID_EQ(f0, n0) && !PP_ID_EQ(g0, n0) && !PP_ID_EQ(h0, n0) && !PP_ID_EQ(i0, n0) && \
     !PP_ID_EQ(j0, n0) && !PP_ID_EQ(k0, n0) && !PP_ID_EQ(l0, n0) && !PP_ID_EQ(m0, n0))
#define _VA_UNIQUE15(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \
    (_VA_UNIQUE14(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) && !PP_ID_EQ(a0, o0) && \
     !PP_ID_EQ(b0, o0) && !PP_ID_EQ(c0, o0) && !PP_ID_EQ(d0, o0) && !PP_ID_EQ(e0, o0) && \
     !PP_ID_EQ(f0, o0) && !PP_ID_EQ(g0, o0) && !PP_ID_EQ(h0, o0) && !PP_ID_EQ(i0, o0) && \
     !PP_ID_EQ(j0, o0) && !PP_ID_EQ(k0, o0) && !PP_ID_EQ(l0, o0) && !PP_ID_EQ(m0, o0) && \
     !PP_ID_EQ(n0, o0))
#define _VA_UNIQUE16(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \
    (_VA_UNIQUE15(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) && !PP_ID_EQ(a0, p0) && \
     !PP_ID_EQ(b0, p0) && !PP_ID_EQ(c0, p0) && !PP_ID_EQ(d0, p0) && !PP_ID_EQ(e0, p0) && \
     !PP_ID_EQ(f0, p0) && !PP_ID_EQ(g0, p0) && !PP_ID_EQ(h0, p0) && !PP_ID_EQ(i0, p0) && \
     !PP_ID_EQ(j0, p0) && !PP_ID_EQ(k0, p0) && !PP_ID_EQ(l0, p0) && !PP_ID_EQ(m0, p0) && \
     !PP_ID_EQ(n0, p0) && !PP_ID_EQ(o0, p0))

/* reusable UNIQUE macro */
#define UNIQUE(...) VA_NARGS_CALL_OVERLOAD(_VA_UNIQUE, __VA_ARGS__)


/* -------------------------------------------------------------------- */
/* ELEM#(v, ...): is the first arg equal any others? */
/* internal helpers*/
#define _VA_ELEM2(v, a) \
       ((v) == (a))
#define _VA_ELEM3(v, a, b) \
       (_VA_ELEM2(v, a) || ((v) == (b)))
#define _VA_ELEM4(v, a, b, c) \
       (_VA_ELEM3(v, a, b) || ((v) == (c)))
#define _VA_ELEM5(v, a, b, c, d) \
       (_VA_ELEM4(v, a, b, c) || ((v) == (d)))
#define _VA_ELEM6(v, a, b, c, d, e) \
       (_VA_ELEM5(v, a, b, c, d) || ((v) == (e)))
#define _VA_ELEM7(v, a, b, c, d, e, f) \
       (_VA_ELEM6(v, a, b, c, d, e) || ((v) == (f)))
#define _VA_ELEM8(v, a, b, c, d, e, f, g) \
       (_VA_ELEM7(v, a, b, c, d, e, f) || ((v) == (g)))
#define _VA_ELEM9(v, a, b, c, d, e, f, g, h) \
       (_VA_ELEM8(v, a, b, c, d, e, f, g) || ((v) == (h)))
#define _VA_ELEM10(v, a, b, c, d, e, f, g, h, i) \
       (_VA_ELEM9(v, a, b, c, d, e, f, g, h) || ((v) == (i)))
#define _VA_ELEM11(v, a, b, c, d, e, f, g, h, i, j) \
       (_VA_ELEM10(v, a, b, c, d, e, f, g, h, i) || ((v) == (j)))
#define _VA_ELEM12(v, a, b, c, d, e, f, g, h, i, j, k) \
       (_VA_ELEM11(v, a, b, c, d, e, f, g, h, i, j) || ((v) == (k)))
#define _VA_ELEM13(v, a, b, c, d, e, f, g, h, i, j, k, l) \
       (_VA_ELEM12(v, a, b, c, d, e, f, g, h, i, j, k) || ((v) == (l)))
#define _VA_ELEM14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) \
       (_VA_ELEM13(v, a, b, c, d, e, f, g, h, i, j, k, l) || ((v) == (m)))
#define _VA_ELEM15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
       (_VA_ELEM14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) || ((v) == (n)))
#define _VA_ELEM16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
       (_VA_ELEM15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) || ((v) == (o)))
#define _VA_ELEM17(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
       (_VA_ELEM16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) || ((v) == (p)))

/* reusable ELEM macro */
#define ELEM(...) ((void)(sizeof(int[UNIQUE(__VA_ARGS__) ? 1 : -1])), \
                  VA_NARGS_CALL_OVERLOAD(_VA_ELEM, __VA_ARGS__))

与gcc5.2测试

Tested with gcc5.2

这篇关于是否有可能prevent重复,相同的参数在C宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆