模数使用字符串大小奇怪的行为

Modulus using string size weird behavior

请解释为什么第一段代码没有产生 -1。

    string s = "abc";
    int amount = -1;
    cout << "amount to shift before modulus: " << amount<<endl;
    amount %= s.size();
    cout << "mod " <<s.size()<<endl;
    cout << "amount to shift after modulus: " << amount<<endl;

输出:
在 modulus 之前转移的金额:-1
mod3
在 modulus 之后转移的金额:0

    string s = "abc";
    int sSize = s.size();
    int amount = -1;
    cout << "amount to shift before modulus: " << amount<<endl;
    amount %= sSize;
    cout << "mod " <<sSize<<endl;
    cout << "amount to shift after modulus: " << amount<<endl;

输出:
在 modulus 之前转移的金额:-1
mod3
在 modulus 之后转移的金额:-1

当我 运行 遇到这种行为时,我正在完成编码挑战,但我不明白发生了什么。如果金额为正数(例如 1),则不会发生此行为。

如果在有符号整数和无符号整数之间进行算术运算(包括算术比较),并且无符号整数类型至少与有符号整数一样宽,则有符号整数转换为无符号整数。 (这就是所谓的"usual arithmetic conversions"的结果。)

这几乎总是有意想不到的结果,除非算术运算是加法或减法。在许多情况下,如果您请求警告,一个好的编译器会警告您进行混合符号算术。 (强烈推荐!)这只是一种相对不常见的变体。

第一种情况,s.size()size_t类型,是无符号类型,大概是64位;因此,它比 int 更宽。因此,为了计算 amount % s.size(),编译器首先将 amount 转换为无符号的 size_t,这将导致 264-1。碰巧,这个数字可以被 3 整除,所以模运算 returns 0.

在第二种情况下,您强制将 s.size() 转换为有符号整数。由于该值肯定在 int 的范围内,因此转换是明确定义的。随后的模运算在 int 上执行,如果您希望带符号的模以它在 C++ 中的方式工作,则它会产生预期的结果。 (有关详细信息,请参阅 Why does C++ output negative numbers when using modulo?。)