如何用C预处理器编写while循环?

我是从教育/黑客的角度提出这个问题的(我真的不想这样编码)。

是否可以仅使用C预处理程序指令来实现while循环。我知道宏不能递归扩展,那么如何实现呢?


慕婉清6462132
浏览 709回答 3
3回答

哔哔one

如果要实现while循环,则需要在预处理器中使用递归。进行递归的最简单方法是使用延迟表达式。延迟表达式是需要更多扫描才能完全扩展的表达式:#define EMPTY()#define DEFER(id) id EMPTY()#define OBSTRUCT(id) id DEFER(EMPTY)()#define EXPAND(...) __VA_ARGS__#define A() 123A() // Expands to 123DEFER(A)() // Expands to A () because it requires one more scan to fully expandEXPAND(DEFER(A)()) // Expands to 123, because the EXPAND macro forces another scan为什么这很重要?当宏被扫描并扩展时,它会创建一个禁用上下文。此禁用上下文将导致标记为蓝色,该标记指向当前正在扩展的宏。因此,一旦将其涂成蓝色,宏将不再扩展。这就是为什么宏不递归扩展的原因。但是,禁用上下文仅在一次扫描期间存在,因此通过延迟扩展,我们可以防止宏变成蓝色。我们只需要对表达式进行更多扫描即可。我们可以使用以下EVAL宏来做到这一点:#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__接下来,我们定义一些用于执行某些逻辑的运算符(例如if等):#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__#define CHECK_N(x, n, ...) n#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x))#define NOT_0 ~, 1,#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)#define COMPL_0 1#define COMPL_1 0#define BOOL(x) COMPL(NOT(x))#define IIF(c) PRIMITIVE_CAT(IIF_, c)#define IIF_0(t, ...) __VA_ARGS__#define IIF_1(t, ...) t#define IF(c) IIF(BOOL(c))现在,使用所有这些宏,我们可以编写一个递归WHILE宏。我们使用WHILE_INDIRECT宏来递归地引用自身。这可以防止宏被涂成蓝色,因为它将在不同的扫描(并使用不同的禁用上下文)下扩展。该WHILE宏带有一个谓词宏,一个运算符宏和一个状态(即可变参数)。它将继续将此运算符宏应用于状态,直到谓词宏返回false(为0)。#define WHILE(pred, op, ...) \    IF(pred(__VA_ARGS__)) \    ( \        OBSTRUCT(WHILE_INDIRECT) () \        ( \            pred, op, op(__VA_ARGS__) \        ), \        __VA_ARGS__ \    )#define WHILE_INDIRECT() WHILE出于演示目的,我们将创建一个谓词,以检查何时参数数量为1:#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)#define IS_1(x) CHECK(PRIMITIVE_CAT(IS_1_, x))#define IS_1_1 ~, 1,#define PRED(x, ...) COMPL(IS_1(NARGS(__VA_ARGS__)))接下来,我们创建一个运算符,将只连接两个令牌。我们还创建了一个最终运算符(称为M),用于处理最终输出:#define OP(x, y, ...) CAT(x, y), __VA_ARGS__ #define M(...) CAT(__VA_ARGS__)然后使用WHILE宏:M(EVAL(WHILE(PRED, OP, x, y, z))) //Expands to xyz当然,任何种类的谓词或运算符都可以传递给它。

炎炎设计

好吧,这不是一个while循环,而是一个计数器循环,尽管如此,在干净的CPP中也可以循环(没有模板,也没有C ++)#ifdef pad_always#define pad(p,f) p##0#else#define pad0(p,not_used) p#define pad1(p,not_used) p##0#define pad(p,f) pad##f(p,)#endif// f - padding flag// p - prefix so far// a,b,c - digits// x - action to invoke#define n0(p,x)#define n1(p,x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;x(p##1)#define n2(p,x) n1(p,x) x(p##2)#define n3(p,x) n2(p,x) x(p##3)#define n4(p,x) n3(p,x) x(p##4)#define n5(p,x) n4(p,x) x(p##5)#define n6(p,x) n5(p,x) x(p##6)#define n7(p,x) n6(p,x) x(p##7)#define n8(p,x) n7(p,x) x(p##8)#define n9(p,x) n8(p,x) x(p##9)#define n00(f,p,a,x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;n##a(pad(p,f),x)#define n10(f,p,a,x) n00(f,p,9,x) x(p##10) n##a(p##1,x)#define n20(f,p,a,x) n10(f,p,9,x) x(p##20) n##a(p##2,x)#define n30(f,p,a,x) n20(f,p,9,x) x(p##30) n##a(p##3,x)#define n40(f,p,a,x) n30(f,p,9,x) x(p##40) n##a(p##4,x)#define n50(f,p,a,x) n40(f,p,9,x) x(p##50) n##a(p##5,x)#define n60(f,p,a,x) n50(f,p,9,x) x(p##60) n##a(p##6,x)#define n70(f,p,a,x) n60(f,p,9,x) x(p##70) n##a(p##7,x)#define n80(f,p,a,x) n70(f,p,9,x) x(p##80) n##a(p##8,x)#define n90(f,p,a,x) n80(f,p,9,x) x(p##90) n##a(p##9,x)#define n000(f,p,a,b,x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;n##a##0(f,pad(p,f),b,x)#define n100(f,p,a,b,x) n000(f,p,9,9,x) x(p##100) n##a##0(1,p##1,b,x)#define n200(f,p,a,b,x) n100(f,p,9,9,x) x(p##200) n##a##0(1,p##2,b,x)#define n300(f,p,a,b,x) n200(f,p,9,9,x) x(p##300) n##a##0(1,p##3,b,x)#define n400(f,p,a,b,x) n300(f,p,9,9,x) x(p##400) n##a##0(1,p##4,b,x)#define n500(f,p,a,b,x) n400(f,p,9,9,x) x(p##500) n##a##0(1,p##5,b,x)#define n600(f,p,a,b,x) n500(f,p,9,9,x) x(p##600) n##a##0(1,p##6,b,x)#define n700(f,p,a,b,x) n600(f,p,9,9,x) x(p##700) n##a##0(1,p##7,b,x)#define n800(f,p,a,b,x) n700(f,p,9,9,x) x(p##800) n##a##0(1,p##8,b,x)#define n900(f,p,a,b,x) n800(f,p,9,9,x) x(p##900) n##a##0(1,p##9,b,x)#define n0000(f,p,a,b,c,x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;n##a##00(f,pad(p,f),b,c,x)#define n1000(f,p,a,b,c,x) n0000(f,p,9,9,9,x) x(p##1000) n##a##00(1,p##1,b,c,x)#define n2000(f,p,a,b,c,x) n1000(f,p,9,9,9,x) x(p##2000) n##a##00(1,p##2,b,c,x)#define n3000(f,p,a,b,c,x) n2000(f,p,9,9,9,x) x(p##3000) n##a##00(1,p##3,b,c,x)#define n4000(f,p,a,b,c,x) n3000(f,p,9,9,9,x) x(p##4000) n##a##00(1,p##4,b,c,x)#define n5000(f,p,a,b,c,x) n4000(f,p,9,9,9,x) x(p##5000) n##a##00(1,p##5,b,c,x)#define n6000(f,p,a,b,c,x) n5000(f,p,9,9,9,x) x(p##6000) n##a##00(1,p##6,b,c,x)#define n7000(f,p,a,b,c,x) n6000(f,p,9,9,9,x) x(p##7000) n##a##00(1,p##7,b,c,x)#define n8000(f,p,a,b,c,x) n7000(f,p,9,9,9,x) x(p##8000) n##a##00(1,p##8,b,c,x)#define n9000(f,p,a,b,c,x) n8000(f,p,9,9,9,x) x(p##9000) n##a##00(1,p##9,b,c,x)#define n00000(f,p,a,b,c,d,x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;n##a##000(f,pad(p,f),b,c,d,x)#define n10000(f,p,a,b,c,d,x) n00000(f,p,9,9,9,9,x) x(p##10000) n##a##000(1,p##1,b,c,d,x)#define n20000(f,p,a,b,c,d,x) n10000(f,p,9,9,9,9,x) x(p##20000) n##a##000(1,p##2,b,c,d,x)#define n30000(f,p,a,b,c,d,x) n20000(f,p,9,9,9,9,x) x(p##30000) n##a##000(1,p##3,b,c,d,x)#define n40000(f,p,a,b,c,d,x) n30000(f,p,9,9,9,9,x) x(p##40000) n##a##000(1,p##4,b,c,d,x)#define n50000(f,p,a,b,c,d,x) n40000(f,p,9,9,9,9,x) x(p##50000) n##a##000(1,p##5,b,c,d,x)#define n60000(f,p,a,b,c,d,x) n50000(f,p,9,9,9,9,x) x(p##60000) n##a##000(1,p##6,b,c,d,x)#define n70000(f,p,a,b,c,d,x) n60000(f,p,9,9,9,9,x) x(p##70000) n##a##000(1,p##7,b,c,d,x)#define n80000(f,p,a,b,c,d,x) n70000(f,p,9,9,9,9,x) x(p##80000) n##a##000(1,p##8,b,c,d,x)#define n90000(f,p,a,b,c,d,x) n80000(f,p,9,9,9,9,x) x(p##90000) n##a##000(1,p##9,b,c,d,x)#define cycle5(c1,c2,c3,c4,c5,x) n##c1##0000(0,,c2,c3,c4,c5,x)#define cycle4(c1,c2,c3,c4,x) n##c1##000(0,,c2,c3,c4,x)#define cycle3(c1,c2,c3,x) n##c1##00(0,,c2,c3,x)#define cycle2(c1,c2,x) n##c1##0(0,,c2,x)#define cycle1(c1,x) n##c1(,x)#define concat(a,b,c) a##b##c#define ck(arg) a[concat(,arg,-1)]++;#define SIZEOF(x) (sizeof(x) / sizeof((x)[0]))void check5(void){&nbsp; &nbsp; int i, a[32769];&nbsp; &nbsp; for (i = 0; i < SIZEOF(a); i++) a[i]=0;&nbsp; &nbsp; cycle5(3,2,7,6,9,ck);&nbsp; &nbsp; for (i = 0; i < SIZEOF(a); i++) if (a[i] != 1) printf("5: [%d] = %d\n", i+1, a[i]);}
打开App,查看更多内容
随时随地看视频慕课网APP