Problem with array indexing on nano

I am porting working code from a UNO R4 WIFI to a nano and seem have a very odd problem. The value of the last ( and sometimes first) value of the array gets corrupted. That is, the second time I access the array the values are changed from the value originally set. In the code below I've stripped out almost everything to illustrate the problem but will reiterate: this code works perfectly on the UNO R4.
I thought the first nano was defective, tried another - same result. This is the first time I've worked with a nano so there maybe some idiosyncrasy I'm not expecting.
Any help would be appreciated.

int maxPow;
int pow2;
int minPin;
int maxPin = 8;
int currentVal;
int maxVal = 15;
int maxIndex = 3;

void setup() {
  Serial.begin(9600);
  maxPow = log(maxVal)/log(2);

  minPin = maxPin - maxPow;
  Serial.println("maxPow = " + String(maxPow, DEC) + "  minPin = " + String(minPin, DEC));  
  delay(longPulse);
  int i;
  int j;
  int k;
  int pins[maxIndex];

  //Create array and print it out immediately
  for(j=0;j<=maxIndex;++j){
    pins[j] = maxPin - j;
    Serial.println("first time: pins[" + String(j, DEC) + "]: " + String(pins[j], DEC));
  }

  // Print it out again
  for(k=0;k<=maxIndex;++k){
    Serial.println("second time: pins[" + String(k, DEC) + "]: " + String(pins[k], DEC));
}

}

void loop() {

}

Should create a 4 element array with the numbers 8-5 descending, then print it out immediately as created and then in a second for loop.
Should be super simple.

This is the result from the nano:
first time: pins[0]: 8
first time: pins[1]: 7
first time: pins[2]: 6
first time: pins[3]: 5
second time: pins[0]: 8
second time: pins[1]: 7
second time: pins[2]: 6
second time: pins[3]: 520

Result from the UNO:
first time: pins[0]: 8
first time: pins[1]: 7
first time: pins[2]: 6
first time: pins[3]: 5
second time: pins[0]: 8
second time: pins[1]: 7
second time: pins[2]: 6
second time: pins[3]: 5

One more thing - when I change the creation of the array to a single line and then print it out the first for loop also fails:

int pins[maxIndex] = {8,7,6,3};
for(j=0;j<=maxIndex;++j){
//pins[j] = maxPin - j;
Serial.println("first time: pins[" + String(j, DEC) + "]: " + String(pins[j], DEC));
}

for(k=0;k<=maxIndex;++k){
Serial.println("second time: pins[" + String(k, DEC) + "]: " + String(pins[k], DEC));
}

produces
first time: pins[0]: 8
first time: pins[1]: 7
first time: pins[2]: 6
first time: pins[3]: 520
second time: pins[0]: 8
second time: pins[1]: 7
second time: pins[2]: 6
second time: pins[3]: 520

Wrap all your code in code blocks.

It is in a code block.
The second set of code is not complete, it's just for clarification.

  int pins[maxIndex];

  //Create array and print it out immediately
  for(j=0;j<=maxIndex;++j){
    pins[j] = maxPin - j;
    Serial.println("first time: pins[" + String(j, DEC) + "]: " + String(pins[j], DEC));
  }

maxIndex is 3.
The pins array therefore has 3 elements.
In the for loop, pins[j] with j = maxIndex is writing to the 4th element of a 3-element array.

You likely did not notice on the Uno R4 WiFi because whatever was being overwritten was not obvious.

No. You missed some. Follow the guidelines.

So if you really want the last index to be maxIndex, as numbering starts at 0, you need maxIndex+1 éléments in the array.

Define it like this

int pins[maxIndex+1];

Then your for loops are legit.

Some might say instead of going around with maxIndex being the last legit number usable as an array index, the variable should be named something like numberOfElements. Which I'll cut short to nElements below. Name it better.

Then arrays are dimensioned naturally:

int someArray[nElements];

And for loops take an idiomatic pattern C/C++ programmers recognize as doing something N times, or doing something for N things numbered from zero to N - 1. Remarkable is the absence of any addition or subtraction to "correct" things that would otherwise be off by one.

  for (byte ii = 0; ii < nElements; ii++) {
    Serial.println(someArray[ii]):
  }

It's just more of getting accustomed to thinking about 0 as a perfectly good number and the way arrays work in C/C++.

The final trick is letting the compiler count the elements

const byte inputPins[] = {2, 3, 6, 7, A0, };
const byte nInputs = sizeof inputPins / sizeof *inputPins;

And use nInputs, the number of elements in the array at indices 0 .. (nInputs - 1) everywhere instead of the literal number you used to initialise your numberOf or maxIndex variable.

a7

I told chatGPT to rewrite my post and gave it no specific goals. Here's what it said I said. :expressionless:

Some people argue that, instead of using a variable like maxIndex to represent the highest usable array index, a better name would be something like numberOfElements — let’s say nElements for short.

The beauty of this approach is that arrays become easier to reason about:

int someArray[nElements];

And the loop pattern that follows is instantly familiar to any C or C++ programmer. It's the classic idiom for doing something n times — or operating on n items, indexed from 0 to n - 1:

for (byte ii = 0; ii < nElements; ii++) {
  Serial.println(someArray[ii]);
}

No -1s, no +1s, no correcting for an off-by-one mistake you already made but haven’t found yet. It just works. The loop does exactly what it says: starts at zero, runs while less than nElements.

It's really just a matter of getting used to thinking of 0 as a perfectly fine number — as a valid place to start — and embracing how arrays naturally behave in C and C++.

And then there’s the ultimate move: let the compiler do the counting for you.

const byte inputPins[] = {2, 3, 6, 7, A0};
const byte nInputs = sizeof inputPins / sizeof *inputPins;

Now nInputs holds the number of elements in the array — automatically. You never have to count by hand, and you never need to go back and change a literal if the array grows.

And everywhere you would have used a magic number or a questionable maxIndex, just use nInputs — because that’s what you really meant: the number of valid entries in the array, accessible from index 0 through nInputs - 1.

chatGPT

You can clearly see that in the output I provided.

You will get better results when you ask for clarification, rather than getting snappy, like you did at me for telling you to format your code (which you did not). BUT, that happens when you first post on the forum... so, please, correct the code not in the code block, like we all do... and your problems will be solved.

Nope - you were right. I looked at that for hours and just missed it.

Bravo!

That's the way I do things!

I couldn't help but remember the quote:

“Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.” - Stan Kelly-Bootle

I'd go a step further:

#define sizeOfArray(x) (sizeof((x)) / sizeof((x)[0]))

for (byte ii = 0; ii < sizeOfArray( someArray ) ; ii++) {
Serial.println(someArray[ii]):
}

LOL.

I have an uneasy feeling that if we hang on for a few more years arrays may indeed be indexed differently. :expressionless:

a7

Go all the way

for (auto&& value : someArray)  Serial.printn(value);

No index = no overflow :slight_smile: