Search code examples
c++gccunsigned-integercompiler-bug

Is there a difference between unary - and n -


I am fairly certain that subtracting one uint8_t from another should result in another unsigned number, but some of my results are confusing me.

  uint8_t a = 2;
  uint8_t b = 1;
  uint8_t c = -a;
  long d = b - a;
  long e = b + c;

When I obtain the value of d it produces -1, while e is as I would expect 255. This is a bug with the version of gcc I am using.....right?

For reference I am using the arm-none-eabi-g++ compiler for my MSP-432.

Looking at this seems to indicate that gcc just seems to make the same mistake here.

Looking at this SO question it seems that godbolt and the arm gcc is wrong.

What is going on here?


Solution

  • This is a bug with the version of gcc I am using.....right?

    No, it's not. Something that simple being buggy in a big compiler like gcc is highly unlikely.

    What happens is due to the "usual arithmetic conversions", specifically "integer promotion":

    The unary - promotes a to int, then the (int)-2 gets converted back to uint8_t in the assignment, yielding c == 254 (which is the representative of the equivalence class of -2 in Z mod 2^8 that lies in [0, 2^8)).

    Likewise, the binary + and - in the lines below that promote to int, so we end up with

    d == (int)b - (int)a == (int)1 - (int)2 == -1
    

    and

    e == (int)b + (int)c == (int)1 + (int)254 == 255
    

    So everything is working fine as mandated by the standard.