What does the third “for” mean in #define for for (int z = 0; z <2; ++ z) for

I found a piece of code in a C ++ program, it seems that it loops twice each for() loop in this program, but why do we need this third one to define such a preprocessor?

#define for for(int z=0;z<2;++z)for

+5
source share
3 answers

It replaces for with for(int z=0;z<2;++z)for . Obviously this would turn

 for (int i = 0; i < N; ++i) { // ... } 

in

 for (int z=0;z<2;++z) for (int i = 0; i < N; ++i) { // ... } 

Thus, two nested loops are created. Without this extra for it will be

 for (int z=0;z<2;++z) (int i = 0; i < N; ++i) { // ... } 

This is clearly wrong.

Please note that even if this is “correct” in the form that you gave in your question, this does not mean that it is “good practice”. This is an example of excessive abuse of macros and should be avoided. Here is one of many examples of how this might go wrong:

 for (int z = 0; z < 5; ++z) { for (int i = 0; i < 3; ++i) { std::cout << z << std::endl; // this will never print 2, 3, 4 } } 

It will expand to

 for (int z=0;z<2;++z) for (int z = 0; z < 5; ++z) { for (int z=0;z<2;++z) for (int i = 0; i < 3; ++i) { std::cout << z << std::endl; // this will never print 2, 3, 4 } } 

We believe that now you have four nested loops, and that the inner loop will print the “invisible” z instead of z , which you declared in the outer loop (which becomes a second-level loop in the extended code).

Another reason: as @stefan pointed out, it is a very bad idea to use keywords or other well-known identifiers as macro names. Makes you think of the infamous #define true false . And, as @HolyBlackCat mentions, this is also undefined behavior, which means that anything can happen with respect to the standard. Because of the code that “seems to work” for the full-blown World War III with the Martians (who invaded Earth to clear it of the ugly code).

+9
source

First off, this macro is the ugliest thing I've ever seen. I do not recommend ever doing something like this.

The main answer of Sergey Takhonov is really wonderful, but it should also be mentioned that this macro does loop each cycle twice. This means that the double nested loops shown below will execute 400 times (not 200 times)! This may be unexpected.

 for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { // I'll be executed 100 times without the macro } } 

becomes

 for (int z=0;z<2;++z) for (int i = 0; i < 10; i++) { for (int z=0;z<2;++z) for (int j = 0; j < 10; j++) { // I'll be executed 400 times with the macro } } 

It only gets worse from here. Consider the infinte loop, for example

 int some_condition = 0; for(;;) { // insert logic here for calculating whether to break out if (some_condition) { some_condition = 0; // set back to false for use down the line break; } } 

turns into

 int some_condition = 0; for (int z=0;z<2;++z) for (;;) { // insert logic here for calculating whether to break out if (some_condition) { some_condition = 0; // set back to false for use down the line break; // gets me out of for(;;)...but the outer loop repeats } } 

which knocks you out of the inner infinite loop if the condition is fulfilled ... just to return back to it. Now you can get stuck in an endless loop.

Unexpected behavior is a good reason to avoid something, and macro-mangans like this are very dangerous and can be real b ** ch for debugging. Imagine if some include directive includes this porting to multiple header files deeply ...

+2
source

Subprocess replacement is performed in a single pass and does not support recursion. Thus, the second “for” is probably related to some conceptual idea of ​​the chain of existing “for” loops, adding them to the “for” macro of the loop part.

 #define for for(int z=0;z<2;++z)for 

So it replaces

 for (int i = 0; i < N; ++i) { // ... } 

with

 for(int z=0;z<2;++z) for (int i = 0; i < N; ++i) { // ... } 

This is a pretty crazy use for the preprocessor.

0
source

Source: https://habr.com/ru/post/1246733/