6

Given this Example:

std::vector<int> numbers = {5,6,7}; //size is 3
int i = -1; 
std::cout << i % 3 <<"\n";                  // output: -1
std::cout << i % numbers.size() << "\n";    // output: 0

basically in both statements im processing -1 % 3 but the compiler outputs different numbers. I don't understand this outcome, maybe someone can explain it to me.

edit: as @Chris,@Keith Thompson @AnT suggested the snippet

std::cout << std::numeric_limits<std::size_t>::max() % 3 <<"\n";     //output: 0
std::cout << i % numbers.size() << "\n";                            // output: 0

prints the expected output. Thanks for the helpful advice to everyone!

Grundkurs
  • 177
  • 1
  • 8
  • See Here: http://stackoverflow.com/questions/7594508/modulo-operator-with-negative-values – Rollen Mar 26 '15 at 01:31
  • 2
    @RollenD'Souza: That's actually unrelated. – Deduplicator Mar 26 '15 at 01:33
  • 2
    The problem is that "numbers.size()" happens to be "unsigned int"; and the "-1" is converted to "0xffffffff" (or whatever the value for your architecture) behind your back :( – FoggyDay Mar 26 '15 at 01:39
  • 1
    @FoggyDay: No, the `-1` isn't converted to `1`. It's converted to `SIZE_MAX`. – Keith Thompson Mar 26 '15 at 01:39
  • @Grundkurs: `i % numbers.size()` is not `-1 % 3`. It is actually `(std::vector::size_type) i % numbers.size()`. And `(std::vector::size_type) i` is no longer `-1`. It is some large unsigned value. – AnT Mar 26 '15 at 01:40

2 Answers2

8

i % 3 is what you expect and, since C++11, has defined semantics rather than having an implementation-defined (if I recall correctly) result.

numbers.size() has an unsigned type (std::size_t). Assuming size_t is as big as int or bigger, i is converted to the same unsigned type before the operation is performed. The value i gets will be the maximum value for that type, which looks to be divisible by 3 for you.

chris
  • 58,138
  • 13
  • 137
  • 194
  • 3
    As a side-note, cranking up the warning-level on the compiler should have caught the sign-mismatch. – Deduplicator Mar 26 '15 at 01:42
  • @Deduplicator, Interesting, I didn't know that. Apparently [Clang doesn't](http://coliru.stacked-crooked.com/a/e425e23f148a1f03), [nor GCC](http://coliru.stacked-crooked.com/a/7353cc43b82d22c3), or at least these versions. – chris Mar 26 '15 at 01:44
  • Try `-Weverything`, and see which warning they threw out of `-Wextra`. – Deduplicator Mar 26 '15 at 01:48
  • @Deduplicator, Ah, I see. Now I'm thinking of whether it's worth adding that specific warning (`‑Wsign‑conversion`) to my options. Thanks! – chris Mar 26 '15 at 01:49
0

The problem is % of negative numbers is not well-defined in C++.

Joshua
  • 38,744
  • 8
  • 68
  • 123