Odd use of the for syntax

I have come across some code that I don't understand, it involves an odd use of the syntax for the for statement.
I wonder if anyone could explain what it is doing?

cycle(int n)
{
  int m = 0;
  for (; n; m++, n--)
    {
      ctl_board_set_leds(1);  // external function to turn LED on
      delay(m);
      ctl_board_set_leds(0); // external function to turn LED off
      delay(n);
    }

  for (; m; m--, n++)
    {
      ctl_board_set_leds(1);
      delay(m);      
      ctl_board_set_leds(0);
      delay(n);
    }
}

Not a clue Mike, but it does make me hungry for some M&Ms candy.

Lefty

It looks like a PWM system,

turns on LED for m time ( m = 0 and growing )
turns off LED for n time and decreasing.
stops when n=0

then reverses the process.

kinda like a police siren but LED's

There are three parts to the for statement - an initialization section, a conditional section, and an increment section. All three are optional.

  for (; n; m++, n--)

There is no initialization section. This implies that everything that needed initialization was already initialized.

The conditional section is just that n is true (non-zero);

The increment section is incrementing m and decrementing n.

The loop will run until n is 0, incrementing m as it does.

Its odd but by no means uncommon. In C the for loop is purely syntactic sugar:

  for (xxx ; yyyy ; zzz)
  {
    bbbbb
  }

means

  {
    xxxx ;
    while (yyyy)
    {
        bbbbb;
        zzzz;
    }
  }

Or something like that. The comma operator is seldom used except in this context (you are only permitted two semicolons in the for line)

Thanks I thought it might be something like that.

kinda like a police siren but LED's

Yes but the goes so fast it just looks like a constant blink.

By the way it doesn't actually work in an arduino, when I arduinoify it it looks like this:-

void setup(){
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void cycle(int n)
{
  int m = 0;
   for (; n; m++, n--)
    {
      Serial.print(m);
      Serial.print(" ");
      Serial.println(n);
      digitalWrite(13, HIGH);
      delay(m * 100);
      digitalWrite(13, LOW);
      delay(n * 100);
    }

  for (; m; m--, n++)
    {
      Serial.print(m);
      Serial.print(" * ");
      Serial.println(n);

      digitalWrite(13, HIGH);
      delay(m * 100);     
      digitalWrite(13, LOW);
      delay(m * 100);
    }
}

void loop()
{
      cycle(500);
      cycle(800);
      delay(3000);       
}

And what happens is that the first two bytes 0 and 500 are printed out and after that it appears something hangs because nothing actually appears again in the serial monitor.

For the curious, the code came from a demo program for the STM34F discovery board for CrossStudio and it produces just a rapid flashing but then I suspect that is because the processor runs so fast.

The person who wrote cycle assumed int is 32 bits. This may get it working…

void cycle(unsigned n)
{
unsigned m = 0;

  for (xxxx ; yyyy ; zzz)
  {
    bbbbb
  }

==>

  {
    xxxx ;
    while (yyyy)
    {
        bbbbb;
        zzzz;
    }
  }

These behave identical because of the outer { } around the while loop. If these would not be there the xxxx; would be in scope after the loop.

There is also a subtile difference if bbbb; contains the continue; statement, compare these two loops…

void setup()
{
  Serial.begin(115200);
  
  for (int x=0; x<100; x++) 
  {
    continue;
  }
  Serial.print("Hello ");
  
  int x = 0;
  while (x < 100)
  {
    continue;
    x++;
  }
  Serial.println("world!");
}

void loop(){};

So there is definitely a difference… (moving the x++; to above might give rise to other problems e.g. if used as index of an array)

break and continue is precisely why I said "or something like that" :wink: