宏递归扩展到序列

时间:2009-08-17 09:17:34

标签: c++ c-preprocessor

是否可以定义扩展为“BUILD(a, i)”的C / C ++宏“x[0], x[1], x[2], ..., x[i]”?喜欢

#define BUILD(x, 0) x[0]
#define BUILD(x, 1) x[0], x[1]
#define BUILD(x, 2) x[0], x[1], x[2]
...

似乎BOOST_PP_ENUM_PARAMS可以完成这项工作。我想我可以#include boost,但我有兴趣知道它是如何以及为什么有效,任何人都可以解释?

我想调用一个函数f(int, ...),它接受​​N个参数x[i],0< = i< N.已知N为ceil(sizeof(A) / sizeof(B))。所以不幸的是,我无法使用varargs或模板。

3 个答案:

答案 0 :(得分:14)

这是可能的,但你必须做一些手工工作并有一个上限。

#define BUILD0(x) x[0]
#define BUILD1(x) BUILD0(x), x[1]
#define BUILD2(x) BUILD1(x), x[2]
#define BUILD3(x) BUILD2(x), x[3]
#define BUILD(x, i) BUILD##i(x)

请注意i应该是整数文字,而不是常量计算值。

BTW,预处理器比通常更强大,但使用这种功能非常棘手。 Boost提供了一个可以简化某些事情的库,包括迭代。见Boost Preprocessor Library。还有另一个这样的图书馆,但它的名字目前不在我这里。

编辑:boost预处理器库使用类似的技术。通过额外的技巧来解决一些极端情况问题,在更高级别的设施之间共享实现宏,解决编译器错误等...通常的增强复杂性,这在通用库的上下文中是正常的,但有时会妨碍对实施原则。可能最引人注目的技巧是添加间接级别,这样如果第二个参数可以是宏,它就会被扩展。即与

#define BUILD_(x, i) BUILD##i(x)
#define BUILD(x, i) BUILD_(x, i)

可以拨打电话

#define FOO 42
BUILD(x, FOO)

这与我曝光的内容无法实现。

答案 1 :(得分:2)

不,它不是 - 宏不能递归。你发布的宏 不是可变参数,这意味着“具有不同数量的参数”。

答案 2 :(得分:0)

确定, 我遇到了同样的问题,我的目标是使用宏打印N个字节数组的所有值。我假设你有几乎相同的问题。如果是这种情况,这个解决方案应该适合未来类似的问题。

#define HEX_ARRAY_AS_STR(array, len) \
    ({ \
        int print_counter = 0; \
        print_buf = calloc(len*3+1, 1); \
        char *tmp_print_buf = print_buf; \
        uint8_t *array_flower = array;  \
        while(print_counter++ < (len)){ \
            sprintf(tmp_print_buf, "%02X ", *(array_flower)++); \
            tmp_print_buf += 3; \
        } \
        print_buf; \
    })

#define eprintf(...) \
    do{ \
        char *print_buf; \
        printf(__VA_ARGS__); \
        if(print_buf) \
            free(print_buf); \
    }while(0)

int 
main(int argc, char *argv[])
{
    uint8_t sample[] = {0,1,2,3,4,5,6,7};
    eprintf("%s\n", HEX_ARRAY_AS_STR(sample, 8));
    return 0; 
}