Fun with void loop and return

I'm having a little experiment with void loop and "return", and it's not working quite how I wanted. I was hoping that the "return" in codeA would send the sketch back to the start of void loop, bypassing codeB and codeC, so that the serial monitor would just show a stream of codeA's. In fact it's showing codeA, codeB, codeC etc.

Am I not understanding what "return" does, or does how I'm trying to invoke the various loops over-ride the "return?

My code:



void setup() {


  Serial.begin(9600);
  }


void loop() {
  
  codeA();
  codeB();
  codeC();
}

void codeA() {
  Serial.println("codeA");
  delay(500);
  return;  
}

void codeB() {
  Serial.println("codeB");
  delay(500);
}

void codeC() {
  Serial.println("codeC");
  delay(500);
}

Try:

void loop() {
  
  codeA();
  return;
  codeB();
  codeC();
}

codeA() returns void even without the command return; and can return other type arguments (int, float, et c.)

  • Try this addition
void setup()
{
  Serial.begin(115200);  // <————<<<<<    Note baud rate
}

void loop()
 {
  //====================
  //Print the time it takes loop() to loop
  static unsigned long speedTime = 0;
  Serial.print(“Microseconds it takes loop() to execute = ”);
  Serial.println(micros() - speedTime);
  speedTime = micros();
  
  codeA();
  codeB();
  codeC();
}

void codeA() 
{
  Serial.println("codeA");
  //delay(500);
  return;  
}

void codeB() 
{
  Serial.println("codeB");
  //delay(500);
}

void codeC() 
{
  Serial.println("codeC");
  //delay(500);
}

My advice is: don't use return like this. It results in poor program structure. Poor program structure results in bugs and wasted time tracking them down and fixing them.

Instead, use if and/or switch statements. Let loop() run from beginning to end, so wherever you put code in loop() it gets a chance to run when it needs to.

return should in my opinion only be used in functions that return a value. Ideally there should only be one return statement, probably near or at the end of the function.

Rules like these are always for guidance, they are not laws. Very occasionally a situation will come up where breaking them makes sense because maybe it significantly improves the performance or readability/understandability of the code. If you think you found one of those situations, be sceptical and listen carefully to the little voice in your head telling you you are being a fool. There's a good chance it is right.

2 Likes

As others have pointed out, with the three functions occurring in sequence in your loop, the loop code will just execute each in sequence. If you want to [in some cases] prevent the "codeB" or "codeC" functions in your loop from executing, you need some way to "break" out of the main loop early. There are different ways but the easiest is have each function return a true or false and test that in your main loop. Something like:

loop( )
{
  if ( codeA( ) )
    {
    return;
    }
  if ( codeB( ) )
    {
    return;
    }
  codeC( );
}

int codeA( )
{
 return false;
}

int codeB( )
{
  return true;
}

int codeC( )
{
  return true; // don't matter...
}

The codes above are equivalent to the one below."

void codeA() {
  Serial.println("codeA");
  delay(500);
}

The return statement transfers control back to the next line in the main line program (the loop() function) after the completion of the codeA() subroutine.

In the above codes, the return statement is placed after the codeA() function. You are now in trouble to think where does the control goes after completing the codeA() subroutine as the general users of IDE belive that the control remains within the curly brackets of the loop() function?

The codeB() and codeC() subroutines would never be executed.

There's zero trouble or question whatsoever about what happens. Control returns to main() which immediately calls loop() again. The behavior is completely defined. It's exactly the same as what happens when control flow reaches the end of loop().

Which is exactly what @Nick55555 wanted.

1 Like

True, was "whipping it out" so played loose...

Thanks for all the replies, I'm a little clearer now.... :thinking: I've got a larger sketch that is working, but I'm trying to think of ways of improving it without breaking it. But that's a different subject in another post.

No, I think it would be the same subject. If you make a new topic, that would be considered cross-posting, which is against forum rules.

One of the exceptions would be a function that first does some test to see if the code in the function can be executed (i.e. if the input parameters are within some valid range or if some connection is 'ready').
If the function cannot be performed, it will often return false. Else it will continue, do what needs to be done and return true in the end.

You are right, but maybe it is not the best idea to let a beginner program return to a hidden function...
Maybe it is also not a good idea that this hidden function is hidden by Arduino, making people think that arduino language is different ftom C/C++ language...

This is a style issue. I think it is acceptable to have a return right at the start to handle exceptions and one in the end for normal operation. A return halfway may indeed be difficult to find (especially in a deeply nested structure).

On this forum nothing can surprise me anymore...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.