使用其中具有goto和标签的宏展开循环 [英] Unroll a loop using a macro that has a goto and a label in it

查看:138
本文介绍了使用其中具有goto和标签的宏展开循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与C或C ++语言功能严格相关。我不建议将以下代码用作设计模式。我不使用它,也不鼓励它。但是我只是想提高自己的知识!

This question is strictly related to the C or C++ language capabilities. I don't recommend the code below as a design pattern. I don't use it and I don't encourage it. But I'm just curious to improve my knowledge!

我有一个包含标签和goto条件的定义。

I have a define that contains a label and a goto condition.

#define BROP(num, sum)                  \
num = rand_lcg(generated);              \
if (num % 2)                            \
{                                       \
rng1:                                   \
    generated = rand_lcg(generated);    \
    if (generated < 512)                \
        sum -= generated;               \
    else                                \
        goto rng1;                      \
}

后来在代码中我像这样使用它:

And later in the code I use it like this:

for (i = 0; i < iterations; i++)
{
    BROP(num, sum);
    BROP(num, sum);
    BROP(num, sum);
    // ...
}

我最终遇到的情况是

是否存在一个聪明的结构,可以使编译器每次重命名标签时使用?

Is there a smart construct I can use to make the compiler rename the label each time the define is "instantiated"?

我知道所有避免该语句的替代方法,但我仍然不知道问题的答案。

I know of ALL the alternatives of avoiding this statement but still, I don't know the answer to the question.

推荐答案

您确实应该将它做成 ... 循环:

You really should make it a do...while loop:

#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)

请参见用于旧外部做{ ... }而(0)

See this for the old outerdo{...}while(0) trick.

如果(错误地)坚持使用标签并使用 GCC 编译器(或应该与此兼容的 Clang / LLVM ),您可以使用本地标签扩展名(即 __ label __ ...)

If you (wrongly) insist on having a label and are using the GCC compiler (or Clang/LLVM which should be compatible on that), you could use local labels extension (i.e. with __label__ ...)

您也可以从 __ LINE __ 生成标签使用预处理器中的串联编号。

You might also generate the label from the __LINE__ number using concatenation in the preprocessor. Take inspiration from

#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);

在单独的行上。当然,要适应并改进您的需求。

on separate lines. Of course adapt and improve for your need.

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

You definitely should use and trust more the compiler optimization abilities and have static inline functions. Not every test is compiled to a machine branch (e.g. because of CMOV instructions); not every loop is compiled to a machine loop (e.g. because of loop unrolling). You are probably losing your developer's time, and more importantly, you are disabling optimizations by your tricks (so your code will likely go slower, not faster).

如果使用GCC或Clang启用优化和警告:请使用
gcc -Wall -Wextra -O3 -mtune = native

If using GCC or Clang enable optimizations and warnings: so compile with
gcc -Wall -Wextra -O3 -mtune=native

这篇关于使用其中具有goto和标签的宏展开循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆