Razer
Razer

Reputation: 8201

Why is a modulo operation returning an unexpected value

Why is the following code printing 255?

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

int main(void) {
  uint8_t i = 0;
  i = (i - 1) % 16;
  printf("i: %d\n", i);
  return 0;
}

I assumed 15, although i - 1 evaluates to an integer.

Upvotes: 16

Views: 2416

Answers (3)

too honest for this site
too honest for this site

Reputation: 12262

Because of integer promotions in the C standard. Briefly: any type "smaller" than int is converted to int before usage. You cannot avoid this in general.

So what goes on: i is promoted to int. The expression is evaluated as int (the constants you use are int, too). The modulus is -1. This is then converted to uint8_t: 255 by the assignment.

For printf then i is integer-promoted to int (again): (int)255. However, this does no harm.

Note that in C89, for a < 0, a % b is not necessarily negative. It was implementation-defined and could have been 15. However, since C99, -1 % 16 is guaranteed to be -1 as the division has to yield the algebraic quotient.


If you want to make sure the modulus gives a positive result, you have to evaluate the whole expression unsigned by casting i:

i = ((unsigned)i - 1) % 16;

Recommendation: Enable compiler warnings. At least the conversion for the assignment should give a truncation warning.

Upvotes: 16

rcgldr
rcgldr

Reputation: 28808

This works (displays 15) with Microsoft C compiler (no stdint.h, so I used a typedef):

#include <stdio.h>
typedef unsigned char uint8_t;

int main(void) {
    uint8_t i = 0;
    i = (uint8_t)(i - 1) % 16;
    printf("i: %d\n", i);
    return 0;
}

The reason for the 255 is because (i - 1) is promoted to integer, and the integer division used for % in C rounds towards zero instead of negative infinity (rounding towards negative infinity is the way it's done in math, science, and other programming languages). So for C % is zero or has the same sign as the dividend (in this case -1%16 == -1), while in math modulo is zero or has the same sign as the divisor.

Upvotes: 2

John Bupit
John Bupit

Reputation: 10618

This is because -1 % n would return -1 and NOT n - 1 1. Since i in this case is unsigned 8 bit int, it becomes 255.

1 See this question for more details on how modulo for negative integers works in C/C++.

Upvotes: 13

Related Questions