使用预处理器重新定义循环

Redefining for loops with the preprocessor

本文关键字:定义 循环 新定义 预处理 处理器      更新时间:2023-10-16

我想做一些邪恶的事情。我想重新定义for循环来修改条件。有办法做到这一点吗?

GCC文档支持重新定义关键字:http://gcc.gnu.org/onlinedocs/cpp/Macros.html

我想做的是为C++做一个"概率"包装器,看看我是否可以用它做一些有趣的事情

#include <iostream>
#include <cstdlib>
#define P 0.85
#define RANDOM_FLOAT  ((float)rand()/(float)RAND_MAX)
#define RANDOM_CHANCE (RANDOM_FLOAT < P)
#define if(a) if((a) && RANDOM_CHANCE)
#define while(a) while((a) && RANDOM_CHANCE)

// No more for loops or do-while loops
#define do
#define goto
// Doesn't work :(
//#define for(a) for(a) if(!RANDOM_CHANCE) { break; } 

int main() {
    srand(time(NULL));
    //Should output a random list of Y's and N's
    for(int i=0; i < 100; ++i) {
        if(i < 100) {
            std::cout << "Y";
        } else {
            std::cout << "N";
        }
    }
    std::cout << std::endl;
    // Will loop for a while then terminate
    int j = 0;
    while(j < 100) {
        ++j;
        std::cout << j << "n";
    }
   std::cout << std::endl;
   return 0;
}

一个可能更合理的用途是计算运行程序中的循环迭代次数,例如通过映射

for(int i=0; i < 10; ++i)

for(int i=0; i < 10; ++i, ++global_counter)

有可能完成我想做的事情吗?


编辑:谢谢你的回复,我真的很感激!

我可以用它做的一件事是模拟一个公平的硬币(有效地迫使p为0.5),注意如果你有一个有偏差的硬币,Pr(HT)==Pr(TH)。我没有发现这个窍门,但它很有用。这意味着你可以近似P。的任何概率分布

bool coin() {
  bool c1 = false;
  bool c2 = false;
  if(true) {
    c1 = true;
  }
  if(true) {
    c2 = true;
  }
  //If they have different faces.
  bool valid = (c1 && !c2) || (!c1 && c2);
  bool result = c1;
  if(valid) { return result; }
  return coin();
}

您是否尝试将else添加到for循环中?这应该会让它发挥作用。

#define for(a) for(a) if(!RANDOM_CHANCE) { break; } else
for (int i = 0; i < 10; ++i)
{
    // do something
}
/* should roughly compile to:
for (int i = 0; i < 10; ++i) if(!RANDOM_CHANCE) { break; } else
{
    // do something
}
or (differing only in whitespace):
for (int i = 0; i < 10; ++i)
    if(!RANDOM_CHANCE)
    {
        break;
    }
    else
    {
        // do something
    }
*/

您已经展示了它。这里有一个可编译的例子:

#include <iostream>
unsigned globalCounter = 0;
#define for(x)  for(x, ++globalCounter)
int main () {
    for (int i=0; i<10; ++i);
    for (int i=0; i<10; ++i);
    std::cout << globalCounter << 'n';
}

这输出20。然而,像这样的现有代码

for (int i=0; i<x; ++i, foobar+=20)

将中断,因为它现在将两个参数传递给for宏。

您需要的是宏重载或可变宏。后者在C99中得到支持,C++11派生了它,所以如果你想让邪恶发生:

unsigned globalCounter = 0;
#define for(...)  for(__VA_ARGS__, ++globalCounter)
#include <iostream>
void main () {
    int another = 0;
    for (int i=0; i<10; ++i, ++another);
    for (int i=0; i<10; ++i, ++another);
    std::cout << globalCounter << ' ' << another << 'n';
}

然后

g++ --std=c++0x source.cc
./a.out
20 20

我不支持这一点。宏可能会伤害你的孩子。

它不起作用,因为块不再属于for语句。转换为

for (int i=0; i < 100; ++i)
{
   if (!RANDOM_CHANCE)
   {
      break;
   }
}
// unrelated to the 'for' above.
{
    if(i < 100) {
        std::cout << "Y";
    } else {
        std::cout << "N";
    }
}

相反,你可以写

#define for(...) for(__VA_ARGS__) if(RANDOM_CHANCE)

所以代码变成

for (int i=0; i < 100; ++i)
    if (RANDOM_CHANCE)
    {
        if(i < 100) {
            std::cout << "Y";
        } else {
            std::cout << "N";
        }
    }

(注意,我使用了可变宏。)


对于global_counter,如果你能保证增量部分永远不会是空的,那么很容易:

#define for(...) for(__VA_ARGS__, ++ global_counter)

否则(例如,代码中有for(;;)),我认为这是不可能的。