Traps of comparing variables, numbers


Could you post some traps when comparing variables/numbers, with same/different, signed/unsigned datatypes (type casting used/not used), in if conditions or anywhere else?

One pops into my mind right away, the float trap. If I know it correctly:

float dummyFloat = 1.0f;

if (1.0f == dummyFloat)
  //instructions here are not assured to be executed
  //correct ways for float comparison:

Thanks in advance!
Have a nice day

  uint32_t x = ( 0xFFFF + 1 );
  if( x > 1 ) Serial.println( "match" ) ;
  else Serial.println( "nomatch" ) ; 

There is the trap of confusing the assignment operator with the comparison operator

if (i = 0) { ...

Also the trap of comparing c-strings

char a[] = "hello";
char b[] = "hello";

if (a == b) { ...

Why are you asking about this?

I don’t get it, could you explain this a little more?

0xFFFF is only 16 bit, x will not overflow.



Beware of the undefined behaviour with overflows (16 bit integers) . It could be solved by 0xFFFFUL

Edit : corrected reason.

The main reason is to get an overview of these traps.

(Last year I had a problem with int vs. uint comparison, which drove me nuts, but unfortunately I forgot it. Now it really bugs me, and I hope it will come up.)

  for ( uint8_t i = 7 ; i >= 0 ; i-- ){
    // do something 8? times 

Hah, another trap I fell into. I thought you inserted the answer with the serial prints.
Ok, so the original code in #2 will provide “nomatch”.
This example applies for the Arduino IDE, or any IDE?

What will be the result of this?

uint32_t x = ( 65535 + 1 );
if( x > 1 ) Serial.println( "match" ) ;
  else Serial.println( "nomatch" ) ; 

I’ve corrected my explanation above and it appears to be an undefined effect with 16bit integers (for 8bit platforms). I had to try your version to confirm that it behaves differently to my version.

When I deal with a variable which should only get positive values, I like to use unsigned formatter.

For example:

bool error1 = false;
unsigned int errorCounter1 = 0u;

if (*something what implies error*)
  errorCounter1 += 1u;
  if (errorCounter1 >= 10u)
    errorCounter1 = 10u;
    erro1r = true;

But what about uint8_t?

Is there any importance using the formatter when dealing with uint8_t?

bool error2 = false;
uint8_t errorCounter2 = 0u;

if (*something what implies error*)
  errorCounter2 += 1u;
  if (errorCounter2 >= 10u)
    errorCounter2 = 10u;
    error2 = true;

Keeping in mind, that uint8_t can go up to 255 .
So what happens if:

uint8_t dummyB = 255;

if (65535u == dummyB)
  //will this evaulate to true?
  //or dummyB is forced to unsigned int for checking?

You have to look here to see how literals and type suffixes are interpreted and for the type conversion rules.

It is not very transparent.

Thanks for the links, they are difficult to read indeed.

Do you know where true and false are defined? I've read this topic, it says it's in the Arduino.h header file, but it is not. I can't seem to find anywhere else in the avr directory.

The data type bool and the values for true and false are defined in C++ itself. This is completely independent of Arduino.

I see, that's the reason it was removed (the linked topic is more than 2 years old).

Ok, so true (0x1) and false (0x0) are defined by standard, got it.

1.0 could be the same as 1.0001. so it may be better to check if a float is within some tolerance

if (abs(dummyFloat - 1.0) < 0.1)

It changed in Arduino in 2014

many of the excentricities of arduino (e.g. byte is no C++) are captured in Arduino.h which is by default included in all .ino files. it includes the following

#include <stdbool.h>
typedef bool boolean;

so while "bool" is defined by C++, boolean is defined in arduino.h

and while true & false may be defined in C++, they are not in C and therefore stdbool.h defines them (ifndef ++cpluscplus__)

@6v6gt: Thanks, that is a very right to the point link.

@gcjr: Thanks! So stdbool.h is the answer.

I was familiar with the Arduino.h (been there to check e.g. the bitRead define), but never went deeper. However my journey goes on, because if I upload this to an UNO:

#ifndef __cplusplus
Serial.println("__cplusplus not defined");
Serial.println("__cplusplus is defined");

#if __cplusplus < 201103L
Serial.println("__cplusplus < 201103L is used");
#endif /* __cplusplus */

I get "__cplusplus is defined". So from stdbool.h these are only compiled:

#define _Bool bool
#define __bool_true_false_are_defined 1

I guess _Bool is just for a "C99" guy, who would like to use _Bool instead of bool.

But where does bool come from in this case? That is built in the compiler?

Sorry..these things make me itch recently, I'd like to know what's going on.

bool is a C++ data type

If i or any variable is compared to a constant, then this typo can be caught during compilation.
Just have to write the condition inversely like this:

if (0 == i) { ...

This way, if someone makes a mistake and types this:

if (0 = i) { ...

it will cause a compilation error.