使用包含goto和标签的宏展开循环 这个问题与C语言或C++语言的能力严格相关。我不推荐以下代码作为设计模式。我不使用它,也不鼓励它。但我只是想提高我的知识

使用包含goto和标签的宏展开循环 这个问题与C语言或C++语言的能力严格相关。我不推荐以下代码作为设计模式。我不使用它,也不鼓励它。但我只是想提高我的知识,c++,c,compiler-errors,C++,C,Compiler Errors,我有一个包含标签和转到条件的定义 #define BROP(num, sum) \ num = rand_lcg(generated); \ if (num % 2) \ { \ rng1: \ generated = rand_lc

我有一个包含标签和转到条件的定义

#define BROP(num, sum)                  \
num = rand_lcg(generated);              \
if (num % 2)                            \
{                                       \
rng1:                                   \
    generated = rand_lcg(generated);    \
    if (generated < 512)                \
        sum -= generated;               \
    else                                \
        goto rng1;                      \
}
#定义BROP(num,sum)\
num=随机数(已生成)\
如果(数量%2)\
{                                       \
rng1:\
已生成=随机成本(已生成)\
如果(生成<512)\
总和-=生成的\
否则\
后藤rng1\
}
在后面的代码中,我这样使用它:

for (i = 0; i < iterations; i++)
{
    BROP(num, sum);
    BROP(num, sum);
    BROP(num, sum);
    // ...
}
for(i=0;i
我最终会遇到这样的情况:循环被展开,标签被重新定义

是否有一个智能构造可以让编译器在每次定义“实例化”时重命名标签


我知道避免这句话的所有选择,但我仍然不知道问题的答案。

你真的应该把它变成
do
循环:

#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)
由于不清楚的原因,您需要所有这三个宏

和使用

  STUPID_LOOP(x++ < 100);
  STUPID_LOOP(y-- > 0);
dumby_循环(x++<100);
愚蠢的_循环(y-->0);
在不同的线路上。当然,根据您的需要进行调整和改进

您肯定应该更多地使用和信任编译器优化功能,并拥有
静态内联
函数。并非每个测试都编译到机器分支(例如,因为);并非每个循环都编译为机器循环(例如,因为)。您可能正在浪费开发人员的时间,更重要的是,您正在通过技巧禁用优化(因此您的代码可能会变慢,而不是变快)


如果使用GCC或Clang启用优化和警告:那么使用GCC-Wall-Wextra-O3-mtune=native编译,忽略它的原因,以下版本的
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;                      \
}
#定义BROP(num、sum、lbl)\
num=随机数(已生成)\
如果(数量%2)\
{                                       \
lbl:\
已生成=随机成本(已生成)\
如果(生成<512)\
总和-=生成的\
否则\
goto lbl\
}
我把它当作

for (i = 0; i < 1000; i++)
{
    BROP(num,sum, lbl1);
    BROP(num,sum, lbl2);
}
(i=0;i<1000;i++)的

{
BROP(num,sum,lbl1);
BROP(num,sum,lbl2);
}

这不依赖于任何编译器扩展,因此您应该能够在大范围的编译器中使用它。

是否有理由不能在宏中使用
do-while
循环构造而不是
goto
。。。为什么这不是函数?C还是C++?他们是不同的语言!这如何避免分支?每个
if
语句都会生成一个分支,这会使编译器更难为您进行优化。@VAndrei,这真是一个糟糕的策略。标签是用来引导人们回答他们感到舒服的问题的。有没有理由不将循环条件更改为
while(生成<512)
而不是使用单独的
bool
变量?while(再次);添加一个分支?除了我显式编写的分支外,我的代码中不需要任何额外的分支。通过预处理器串联和
\uuuuuuuuuuuuuuuuu
它仍然是可移植的,并且您不必手动发明
lbl2
标签!同意,但我要的是最简单的解决方案。我怀疑这是为了基准测试或测试套件,所以明确的选择通常是更好的选择。
for (i = 0; i < 1000; i++)
{
    BROP(num,sum, lbl1);
    BROP(num,sum, lbl2);
}