csyntaxoperatorsequality

Testing for equality between a uint8_t and an inverted uint8_t does not work as expected


While debugging my implementation of YMODEM on an embedded system, I noticed that some code comparing a uint8_t and the inverse of a uint8_t is not behaving as I expected, but I don't really understand why. To test that this is really the case in C and not just wierd behaviour of my embedded system, I wrote the following

#include <stdio.h>
#include <stdint.h>

int main(int argc, char ** argv)
{
    uint8_t num1 = 0;
    uint8_t num2 = 255;

    printf("%d\n", num1 == ~num2);
    return 0;
}

If I have a uint8_t with the value 0x00, then the inverse should be 0xFF, right? So this program should print 1. However, it prints 0, indicating that 0x00 != ~0xFF.

Why does this happen?


Solution

  • What you're seeing is a result of integer promotion.

    In most expressions, anytime a type smaller than int is used it is first promoted to type int. The == operator and the ~ operator are cases where this applies.

    So in the expression ~num2, the value of num2 (with representation 0xff) is first promoted to type int while retaining the same value and having a representation of 0x000000ff. Then when the ~ operator is applied the result has type int with representation 0xffffff00. This value is not equal to 0, so the comparison fails.

    You'll need to mask off any upper bits after the ~ operator is applied.

    printf("%d\n", num1 == (~num2 & 0xff));