Why doesn't a negative number modulo a vector size give a negative number?

Geo*_*ang 23 c++ integer-promotion modulus

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
  vector<int> v = {1, 2, 3, 4, 5, 6, 7};
  int i = -4;

  cout << i << endl;
  cout << v.size() << endl;
  cout << i % v.size() << endl;
  cout << -4 % 7 << endl;
}
Run Code Online (Sandbox Code Playgroud)

The above code prints:

-4
7
5
-4
Run Code Online (Sandbox Code Playgroud)

Can someone please explain why i % v.size() prints 5 instead of -4? I'm guessing it has something to do with vector.size(), but unsure what the underlying reasoning is. Thanks in advance.

M.M*_*M.M 31

在执行除法之前,的操作数%经过通常的算术转换以将它们转换为通用类型。如果操作数是intsize_t,则 将int转换为size_t

如果size_t是 32 位,-4则将变为4294967292,然后表达式的结果4294957292 % 7实际上是0.

如果size_t是 64 位,那么-4将变成 18,446,744,073,709,551,612,结果% 7就是5你看到的。

所以实际上我们可以从这个输出中看出你的系统有 64 位 size_t。


And*_* H. 9

在 C++ 中,模运算符的定义使得以下对于除 b == 0 之外的所有整数都成立:

(a/b)*b + a%b == a
Run Code Online (Sandbox Code Playgroud)

因此它被迫与整数除法一致,从 C++ 11 开始,即使对于负数,它也会截断为零。因此,即使对于负数,一切都很好定义。

但是,在您的情况下,您有一个有符号/无符号除法(因为 .size() 返回无符号)并且通常的有符号/无符号规则适用。这意味着在这种情况下,在执行操作之前所有参数都被转换为无符号(另见 Ruslan 的评论)。

所以 -4 被转换为无符号(并成为一个非常大的数字),然后进行模运算。

您还可以看到这一点,因为 5 不是带有任何整数除法定义的 -4 模 7 的正确答案(3 是正确的)。

C 和 C++ 的算术规则并不直观。