Simple function doesn't work

I've been trying to improve my code by putting small sections of it into functions. But keep hitting failures like the following.

The code below in setup() works correctly giving a result like 'indexed file number should be 2601'

int s = 0;
      for (int i = 0; i < randNumberF - 1; i++)
      {
        s += folderSizes[i];
      }
    
  Serial.print("indexed file number should be ");
  Serial.println(s);

But after converting the main part to a function, it always prints a zero result. 'indexed file number should be 0'.

int indexShouldBe()
{
  // Calculates number of tracks s in all previous folders
  int s; // Hoped that using 'static' would help, but no
  for (int i = 0; i < randNumberF - 1; i++)
  {
    s += folderSizes[i];
  }
}

You forgot the = 0. There is no guarantee that a local variable will have zero value, unlike a global variable.

Also you forgot to return a value.

  return s;

Without that, the function is returning zero. But even that is not guaranteed, I suspect. If you don't explicitly give a return value, you could get any value.

Not only get any value but it’s UB as you broke the promise made to the compiler so anything can happen - including super weird behavior

—-
The spec states

Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function

Thanks Paul. I had tried both of those specific suggestions, s = 0; and adding return (which I’ve frequently seen left out without an apparent problem) but still got the zero result.

With no return should have generated a warning. Do you have compiler warnings enabled in the IDE, File, Preferences? You should and you should investigate and fix any warnings.

Thanks but sorry I dont understand. What is ‘UB’? What is meant by ‘flowing off the end…’?

UB is for Undefined behavior - cppreference.com

for your code, s is a local variable. Do you have another one which would be global?

post all your code ➜ Don't post snippets (Snippets R Us!)

@groundFungus

Yes, I have All warnings specified.

This verifies OK, no errors.

int indexShouldBe()
{
  // Calculates number of tracks s in all previous folders
  int s = 0; // Hoped that using 'static' would help, but no
  for (int i = 0; i < randNumberF - 1; i++)
  {
    s += folderSizes[i];
  }

  return s;
}

But so does this:

int indexShouldBe()
{
  // Calculates number of tracks s in all previous folders
  int s = 0; // Hoped that using 'static' would help, but no
  for (int i = 0; i < randNumberF - 1; i++)
  {
    s += folderSizes[i];
  }
}

As mentioned, I often see examples here with no 'return' in (non-void) functions.

There are lots of beginners here... that's a bug. Don't do this.

can you post the full code on how you call that function, what's folderSizes and randNumberF etc... ? so many things can go wrong...

I think 570 lines of (unfinished) code would distract. The code shown does work - just not inside my presumably incorrect function. But when i get back to my PC this afternoon I'll reduce it to a self-contained demo sketch for better discussion.

You need to return the value calculated...

int indexShouldBe()
{
  // Calculates number of tracks s in all previous folders
  int s; // Hoped that using 'static' would help, but no
  for (int i = 0; i < randNumberF - 1; i++)
  {
    s += folderSizes[i];
  }

  return s;
}

AND you need to use the value returned by the function in the main code...

  Serial.print("indexed file number should be ");
  Serial.println(indexShouldBe());
1 Like

570 lines is OK as we know where to zoom in for usual issues that you possibly would not think of...

if we can't find it, then sure - a minimal example would be nice

Those are what we call 'bad examples'!

Many thanks, that fixed it!

Confess I still don't understand why I couldn't use the returned variable 's' itself? Although presumably that's why I also had to add another declaration for s before using my original function?

I'll shortly still add the minimised program.

Sounds like you have two variables called 's'. One is local to indexShouldBe(), the other is either global or local to loop(). These have the same name but they are entirely separate variables, each with their own value. When you change one, the other remains unchanged. We say the two variables have different 'scope'.

This line

does not return the variable s. It returns the value in variable s. The variable s itself ceases to exist at the moment the function ends.

1 Like

The word is, SCOPE

seems I got it right there then...

when I said we knew what to look for even in 500+ lines of code...

next time don't ignore the input you get....

Minimised version below.

The original works as expected.

//Define an array of five folder sizes (number of tracks in each)
int folderSizes[] = {96, 106, 229, 159, 188}; // 

void setup()
{

  Serial.begin(115200);
  delay(200); // Time to clear previous printing
  Serial.println("Puzzle_Demo");

  // Sum of the first three folders (96+106+229 = 431)
  // Original successful code
  int s = 0;
  for (int i = 0; i < 3; i++)
  {
    s += folderSizes[i];
  }
  Serial.print("Result = ");
  Serial.println(s);
} // End setup

void loop()
{
}

Then I used that identical code in a function instead. That failed with the error "'s' was not declared in this scope". I added an extra declaration which removed the error but the sketch gave a zero tresult.

//Define an array of five folder sizes (number of tracks in each)
int folderSizes[] = {96, 106, 229, 159, 188}; //

void setup()
{
  Serial.begin(115200);
  delay(200); // Time to clear previous printing
  Serial.println("Puzzle_DemoFunctionFailed");

  // Sum of the first three folders (96+106+229 = 431)
  // Compiled but gave incorrect result (0 instead of 431)
  int s = 0;
  resultShouldBe();
  Serial.print("Result = ");
  Serial.println(s);
} // End setup

void loop()
{
}

int resultShouldBe()
{
  int s = 0;
  for (int i = 0; i < 4 ; i++)
  {
    s += folderSizes[i];
  }
}

Throughout, I regarded the variable 's' as the result I was calculating and wanting to print.

The correct result was obtained by following the crucial advice from @red_car

//Define an array of five folder sizes (number of tracks in each)
int folderSizes[] = {96, 106, 229, 159, 188}; //

void setup()
{
  Serial.begin(115200);
  delay(200); // Time to clear previous printing.
  Serial.println("Puzzle_DemoCorrect");

  // Sum of the first three folders (96+106+229 = 431).
  resultShouldBe();
  Serial.print("Result = ");
  Serial.println(resultShouldBe()); // Crucial edit
} // End setup

void loop()
{
}

int resultShouldBe()
{
  int s = 0;
  for (int i = 0; i < 4 ; i++)
  {
    s += folderSizes[i];
  }
  return s;
}

And following Paul's post #16
"return s; does not return the variable s. It returns the value in variable s. The variable s itself ceases to exist at the moment the function ends"
I now see the fundamental cause of my problem.

Must say that it doesn't square with my intuition though. Having 'returned' s it sort of goes against the grain that I can't use it directly elsewhere!

Valuable learning exercise, thanks to all.

P.S. Note that none of the other 560 lines of code would have helped resolve the issue.

By default, C / C++ functions return by value. You can also return by pointer (which is just really returning the value of the pointer that points to the variable). In C++ you can return by reference. However, trying these last two methods with a (non-static) variable that's local to that function makes no more sense than not using a 'return' statement in a function that promises to return a value. i.e. it makes zero sense.