cunderflow

Why does expanding this C assignment into 2 lines produce a different result?


This code produces the (incorrect) result of 255

#include <stdio.h>

int main()
{
    unsigned char x = 0;
    x = (x-1)%16;
    printf("%d", x);

    return 0;
}

While this code produces the result 15 which I feel is correct

#include <stdio.h>

int main()
{
    unsigned char x = 0;
    x--;
    x %= 16;
    printf("%d", x);

    return 0;
}

I was trying to use an underflow to my advantage when this unexpected result happened.

Problem does not occur with unsigned int or any other unsigned integer type.


Solution

  • See this post. x-1 is implicitly promoted to signed int, effectively becoming -1. -1 % 16 (so "remainder of -1 / 16") is still -1, then it is converted back to unsigned char, which is 255.