此问题与C或C ++语言功能严格相关。我不建议将下面的代码作为设计模式。我不使用它,我不鼓励它。但我只是想提高自己的知识!
我有一个包含标签和转到条件的定义。
#define BROP(num, sum) \
num = rand_lcg(generated); \
if (num % 2) \
{ \
rng1: \
generated = rand_lcg(generated); \
if (generated < 512) \
sum -= generated; \
else \
goto rng1; \
}
稍后在代码中我使用它:
for (i = 0; i < iterations; i++)
{
BROP(num, sum);
BROP(num, sum);
BROP(num, sum);
// ...
}
我最终处于循环展开并且标签重新定义的情况。
我是否可以使用智能构造使编译器在每次定义“实例化”时重命名标签?
我知道避免这种说法的所有选择,但我仍然不知道问题的答案。
答案 0 :(得分:3)
你真的应该让它成为do
... while
循环:
#define BROP(num, sum) do{ \
bool again = false; \
num = rand_lcg(generated); \
if (num % 2) { \
do { again = false; \
generated = rand_lcg(generated); \
if (generated < 512) \
sum -= generated; \
else \
again = true; \
} while(again); } while(0)
有关旧外do{
... }while(0)
技巧,请参阅this。
如果您(错误地)坚持使用标签并使用GCC编译器(或Clang/LLVM应该与之兼容),您可以使用local labels扩展名(即__label__
...)
您也可以使用预处理器中的concatenation从__LINE__
号码生成标签。从
#define STUPID_LOOP_BIS(Test,Lin) do { \
lab##Lin: if (Test) goto lab##Lin; } while(0)
#define STUPID_LOOP_AT(Test,Lin) STUPID_LOOP_BIS(Test,Lin)
#define STUPID_LOOP(Test) STUPID_LOOP_AT(Test,__LINE__)
由于不明原因,您需要所有三个宏!
并使用
STUPID_LOOP(x++ < 100);
STUPID_LOOP(y-- > 0);
在不同的行上。当然,根据您的需要进行调整和改进。
你绝对应该使用信任更多的编译器优化能力并拥有static inline
个功能。并非每个测试都编译到机器分支(例如,因为CMOV instructions);并非每个循环都被编译为机器循环(例如,因为loop unrolling)。您可能正在失去开发人员的时间,更重要的是,您通过技巧禁用优化(因此您的代码可能会变慢,而不是更快)。
如果使用GCC或Clang启用优化和警告:所以使用gcc -Wall -Wextra -O3 -mtune=native
进行编译
答案 1 :(得分:2)
忽略它的原因,以下版本的BROP
完全编译为C和C ++
#define BROP(num, sum, lbl) \
num = rand_lcg(generated); \
if (num % 2) \
{ \
lbl : \
generated = rand_lcg(generated); \
if (generated < 512) \
sum -= generated; \
else \
goto lbl; \
}
我将其作为
调用for (i = 0; i < 1000; i++)
{
BROP(num,sum, lbl1);
BROP(num,sum, lbl2);
}
这不依赖于任何编译器扩展,因此您应该能够在大量编译器中使用它。