我正在尝试构建一个只运行一次代码的宏。 非常有用,例如,如果您循环代码并希望内部的某些事情只发生一次。简单的使用方法:
static int checksum;
for( ; ; )
{
if(checksum == 0) { checksum == 1; // ... }
}
但是有点浪费和困惑。所以我有这个宏,它使用检查位而不是检查变量的真/假状态:
#define CHECKSUM(d) static d checksum_boolean
#define CHECKSUM_IF(x) if( ~(checksum_boolean >> x) & 1) \
{ \
checksum_boolean |= 1 << x;
#define CHECKSUM_END }1
末尾的1
是强制用户在末尾加上分号。在我的编译器中这是允许的。
问题是弄清楚如何在用户不指定 x
(要检查的 n 位)的情况下执行此操作。
所以他可以使用这个:
CHECKSUM(char); // 7 run-once codes can be used
for( ; ; )
{
CHECKSUM_IF
// code..
CHECKSUM_END;
}
关于如何实现这一目标的想法?
最佳答案
我猜你是说你希望宏以某种方式自动跟踪你的位掩码的哪一位包含当前测试的标志。你可以这样做:
#define CHECKSUM(d) static d checksum_boolean; \
d checksum_mask
#define CHECKSUM_START do { checksum_mask = 1; } while (0)
#define CHECKSUM_IF do { \
if (!(checksum_boolean & checksum_mask)) { \
checksum_boolean |= checksum_mask;
#define CHECKSUM_END \
} \
checksum_mask <<= 1; \
} while (0)
#define CHECKSUM_RESET(i) do { checksum_boolean &= ~((uintmax_t) 1 << (i)); } while (0)
你可以这样使用:
CHECKSUM(char); // 7 run-once codes can be used
for( ; ; )
{
CHECKSUM_START;
CHECKSUM_IF
// code..
CHECKSUM_END;
CHECKSUM_IF
// other code..
CHECKSUM_END;
}
但是请注意,这有严重的局限性:
CHECKSUM_START
宏和所有相应的CHECKSUM_IF
宏都必须出现在同一范围内- 控制必须始终在任何
CHECKSUM_IF
block 之前通过CHECKSUM_START
- 控件必须始终以相同的顺序到达
CHECKSUM_IF
block 。它可能只跳过一个CHECKSUM_IF
block ,前提是它还跳过所有使用相同校验和位掩码的后续 block 。
出现这些限制是因为预处理器无法计数。
换句话说,除非重新定义宏,否则没有任何参数的宏总是会扩展为完全相同的文本。因此,如果您不使用宏参数来指示在每种情况下应用哪个标志位,则需要在运行 时对其进行跟踪。
关于c - 运行一次调节的宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29929725/