Compaison Operator doesnt work as expected

Hello,

in my project I discovered some weird behaviour regarding comparison operators. So I took the code apart, trying to find the error but I still cant figure out whats going on.

I expect boolVar to become 0 (false) once i becomes bigger than x. But it doesn’t.
The problem disappeares when I change x=10 to x=5 or tmpArray[ i ] to tmpArray[ 2 ].

Whats going on here?

Code:

int x = 10; //Output is correct when I change this to x=5
int tmpArray[10] = {1,1,1,1,1,1,1,1,1,1};

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  int i=0;

  while( tmpArray[i] != 0 ) //Output is correct when I change this to tmpArray[2] 
  {
    Serial.print("i=");
    Serial.print(i);

    Serial.print("   x=");
    Serial.print(x);
        
    bool boolVar = (i < x);
    Serial.print("   (i < x)=");
    Serial.println(boolVar);
    
    delay(50);
    i++;     
  }
}

Output:

i=0 x=10 (i < x)=1
i=1 x=10 (i < x)=1
i=2 x=10 (i < x)=1
i=3 x=10 (i < x)=1
i=4 x=10 (i < x)=1
i=5 x=10 (i < x)=1
i=6 x=10 (i < x)=1
i=7 x=10 (i < x)=1
i=8 x=10 (i < x)=1
i=9 x=10 (i < x)=1
i=10 x=10 (i < x)=1
i=11 x=10 (i < x)=1
i=12 x=10 (i < x)=1

I notice right off the bat that you're reading off the end of your array once i gets to 10 or more.

Delta_G:
I notice right off the bat that you’re reading off the end of your array once i gets to 10 or more.

Yes, I know that. This is not the code I actually use. Its just a stripped down version where I try to find the mistake.

Yes, I do go beyond the borders of the array, but why would the comparison (i < x) be affected by that. The array is not involved here.

Have you tested this stripped down version? Or are you asking us to debug one piece of code by looking at a different piece of code? Is this the actual code that produced that actual output?

Looks like a case of undefined behavior. It's never valid to access tmpArray past index 9, so the compiler appears to use that knowledge to always set boolVar to true (instead of comparing i with x). The compiler figures that if i becomes greater than 9, who cares what the results of the program are? You're doing something undefined so the results in those cases don't matter. Yes, the compiler really is free to optimize like that, and yes, it sometimes does so.

I finally got next to an Arduino where I could test this code.

I can say i only gets to 29 before it finds a 0 to read and the count starts over:

i=0   x=10   (i < x)=1
i=1   x=10   (i < x)=1
i=2   x=10   (i < x)=1
i=3   x=10   (i < x)=1
i=4   x=10   (i < x)=1
i=5   x=10   (i < x)=1
i=6   x=10   (i < x)=1
i=7   x=10   (i < x)=1
i=8   x=10   (i < x)=1
i=9   x=10   (i < x)=1
i=10   x=10   (i < x)=1
i=11   x=10   (i < x)=1
i=12   x=10   (i < x)=1
i=13   x=10   (i < x)=1
i=14   x=10   (i < x)=1
i=15   x=10   (i < x)=1
i=16   x=10   (i < x)=1
i=17   x=10   (i < x)=1
i=18   x=10   (i < x)=1
i=19   x=10   (i < x)=1
i=20   x=10   (i < x)=1
i=21   x=10   (i < x)=1
i=22   x=10   (i < x)=1
i=23   x=10   (i < x)=1
i=24   x=10   (i < x)=1
i=25   x=10   (i < x)=1
i=26   x=10   (i < x)=1
i=27   x=10   (i < x)=1
i=28   x=10   (i < x)=1
i=29   x=10   (i < x)=1
i=0   x=10   (i < x)=1
i=1   x=10   (i < x)=1
i=2   x=10   (i < x)=1
i=3   x=10   (i < x)=1
i=4   x=10   (i < x)=1
i=5   x=10   (i < x)

However if I add some serial prints to see if it is resetting we find out that it isn’t, but the breakover point changes to 32. This is definitely a result of reading off the end of the array until we find a 0 to stop the while loop:

Starting setup
Starting loop
i=0   x=10   (i < x)=1
i=1   x=10   (i < x)=1
i=2   x=10   (i < x)=1
i=3   x=10   (i < x)=1
i=4   x=10   (i < x)=1
i=5   x=10   (i < x)=1
i=6   x=10   (i < x)=1
i=7   x=10   (i < x)=1
i=8   x=10   (i < x)=1
i=9   x=10   (i < x)=1
i=10   x=10   (i < x)=1
i=11   x=10   (i < x)=1
i=12   x=10   (i < x)=1
i=13   x=10   (i < x)=1
i=14   x=10   (i < x)=1
i=15   x=10   (i < x)=1
i=16   x=10   (i < x)=1
i=17   x=10   (i < x)=1
i=18   x=10   (i < x)=1
i=19   x=10   (i < x)=1
i=20   x=10   (i < x)=1
i=21   x=10   (i < x)=1
i=22   x=10   (i < x)=1
i=23   x=10   (i < x)=1
i=24   x=10   (i < x)=1
i=25   x=10   (i < x)=1
i=26   x=10   (i < x)=1
i=27   x=10   (i < x)=1
i=28   x=10   (i < x)=1
i=29   x=10   (i < x)=1
i=30   x=10   (i < x)=1
i=31   x=10   (i < x)=1
i=32   x=10   (i < x)=1
i=33   x=10   (i < x)=1
i=34   x=10   (i < x)=1
i=35   x=10   (i < x)=1
Starting loop
i=0   x=10   (i < x)=1
i=1   x=10   (i < x)=1
i=2   x=10   (i < x)=1
i=3   x=10   (i < x)=1

If we make sure we don’t overrun the array:

int x = 10; //Output is correct when I change this to x=5
int tmpArray[12] = {1,1,1,1,1,1,1,1,1,1,1,1};

void setup() 
{
  Serial.begin(9600);
  Serial.println("Starting setup");
}

void loop() {
Serial.println("Starting loop");

  int i=0;

  while( tmpArray[i] != 0 ) //Output is correct when I change this to tmpArray[2] 
  {
    Serial.print("i=");
    Serial.print(i);

    Serial.print("   x=");
    Serial.print(x);
        
    bool boolVar = (i < x);
    Serial.print("   (i < x)=");
    Serial.println(boolVar);
    
    delay(50);
    i++;    
    if(i == 12){
      break; 
    }
  }
}

We get the expected output:

Starting setup
Starting loop
i=0   x=10   (i < x)=1
i=1   x=10   (i < x)=1
i=2   x=10   (i < x)=1
i=3   x=10   (i < x)=1
i=4   x=10   (i < x)=1
i=5   x=10   (i < x)=1
i=6   x=10   (i < x)=1
i=7   x=10   (i < x)=1
i=8   x=10   (i < x)=1
i=9   x=10   (i < x)=1
i=10   x=10   (i < x)=0
i=11   x=10   (i < x)=0

So it looks like you’re probably getting bit by the optimizer.

Moral of the story: Keep in bounds on your arrays.

Okay, thank you both for your help and the code examples, I think I got it now!

As soon as the program realizes “Whoops, I am going out of bounds here!” it stops working correctly and does whatever it wants to do.

Which is also the reason why with this code it wont stop:

while( (tmpArray[i] != 0) && (i < 10) )

But with this it does:

while( (i < 10) && (tmpArray[i] != 0))

As soon as I access data outside of my array, I can’t rely on proper results anymore.
Thank you :slight_smile: