impossible to do an infinity FOR loop

Hi

I realized something rather strange while programming something for an Arduino Uno: I was not able to make a "FOR" infinity loop. I've already checked to ensure that it wasn't an overflow problem.

When I'm trying to do that kind of loop the program is running correctly for about two seconds and it's executing what's in the loop and than it just execute the rest of the code.

I solved that problem with a "While" loop but I'd like to know what is causing that problem.

thanks.

Impossible to do an explanation without seeing your code.

Sorry

void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  for(int a =0; true; a=a){
  }
  digitalWrite(13,LOW);
}
void loop() {
  digitalWrite(13, HIGH);   
  delay(1000);              
  digitalWrite(13, LOW);    
  delay(1000);              
}
for (n=whatever;n==n;n += grandmasShoeSize)
  {
   //This will happen an infinite number of times.
   //or at least until the sun goes super nova

  }

An infinite loop is most easily written
while(true) { }
to make it clear there is no break out of the loop.

for ( ; ; ) also works (I think) but is less clear.

Edit: spaces inserted to stop compiler flirting. :wink:

marco_c:
An infinite loop is most easily written
while(true) { }
to make it clear there is no break out of the loop.

for (;:wink: also works (I think) but is less clear.

You need a space in there or else the compiler thinks your flirting with it :wink:

If it must be a "for" loop, then:

for(;;) {}

...will work.

@cr0sh: How about:

#define ever (;;);

void setup() {

   for ever
}

You can use tail recursion for this.

A few karma points to the first person to point out what is significantly out of place in my examples.

void InfiniteLoop(){

  //Loop code here
  return  InfiniteLoop();
}

//Need an index?

void InfiniteLoop(){
  static unsigned long count = 0;
  
  Serial.println( count++ );
  return  InfiniteLoop();
}

//The same thing, but slightly more efficient:
void InfiniteLoop( unsigned long count ){

  Serial.println( count );
  return  InfiniteLoop( count + 1 );
}

//Just call it with the starting index:
void setup() {
  Serial.begin( 115200 );
  InfiniteLoop( 0 );
}

pYro_65:
You can use tail recursion for this.

A few karma points to the first person to point out what is significantly out of place in my examples.

In each of your examples, just before it makes the return it has to make the recursive call, so the stack is going to explode.

KenF:
In each of your examples, just before it makes the return it has to make the recursive call, so the stack is going to explode.

Nope, its called tail recursion and uses the same stack location.

pYro_65:
Nope, its called tail recursion and uses the same stack location.

Interesting, I'd never heard of this optimisation. I assume that it's limited to void types?

A few karma points to the first person to point out what is significantly out of place in my examples.

You don't have loop().

KenF:
Interesting, I'd never heard of this optimisation. I assume that it's limited to void types?

Not necessarily.

In essence (and I discovered a use for this years ago when I was trying to save a few bytes in compiled code) you convert:

  call foo
  ret

To:

  jmp foo

We already have the return code from this function on the stack, so when foo returns it returns to where we want to go, without using extra stack for the call to foo.

KenF:
Interesting, I'd never heard of this optimisation. I assume that it's limited to void types?

No, you can use it to calculate a value.

The limiting factor is the recursive call cannot be in the middle of the function ( because the caller still requires stack for its local vars which do not go out of scope till the closing brace ( after the return ).

unsigned long analogRead( const char pin, const unsigned int count ){
  return analogRead( pin ) + ( count ? analogRead( pin, count - 1 ) : 0 );
}

//...
//Get average of 5000 readings:
Serial.println( analogRead( A0, 5000 ) / 5000 );

Any local var/parameter that has side effects will cause the function to be non tail-recursive. Here the destructor for 'Flash' runs after the return, and as it has side effects out side the scope of the function, it must keep is stack space. And the function will blow the stack:

struct Flash{
  Flash(){ pinMode( 13, OUTPUT ), digitalWrite( 13, HIGH ); }
  ~Flash(){ digitalWrite( 13, LOW ); }
};


unsigned long analogRead( const char pin, const unsigned int count ){
  Flash f;
  return analogRead( pin ) + ( count ? analogRead( pin, count - 1 ) : 0 );
}

By adding a nested scope, you can restrict the life time of a variable, this code is fine:

struct Flash{
  Flash(){ pinMode( 13, OUTPUT ), digitalWrite( 13, HIGH ); }
  ~Flash(){ digitalWrite( 13, LOW ); }
};


unsigned long analogRead( const char pin, const unsigned int count ){
  {Flash f;}
  return analogRead( pin ) + ( count ? analogRead( pin, count - 1 ) : 0 );
}

I added setup in to show how to use it. The code won't compile with a loop() as there are two functions with the same prototype. I just gave 3 different examples of the same recursive function.

  for(int a =0; true; a=a){
  }

Surely the whole point of a for loop is that is executed a predetermined number of times and that the variable is changed in a predictable way on each iteration. If you want a never ending loop then as others have pointed out there are easier ways.

By definition there can only be one infinite loop in a program so what's wrong with the one that comes free with the Arduino system - loop() ?

...R

By definition there can only be one infinite loop in a program ...

Executing at a time.

You may want to go into an infinite loop if you can't open an SD card file, for example, otherwise not.

loop() can easily be used for that

…R