C++似乎违反了加法的性质

12

在完成一项班级作业时,我遇到了这个问题(请注意循环条件)

// This one works.
for (int k = 0; k + negwords[j].length() < comments[i].length(); k++) {
    if (comments[i].substr(k, negwords[j].length()) == negwords[j]) {
        negativeScore++;
    }
}
//*/

/*/ This one doesn't: It fails with an out-of-bounds index.
for (int k = 0; k < comments[i].length() - negwords[j].length(); k++) {
    if (comments[i].substr(k, negwords[j].length()) == negwords[j]) {
        negativeScore++;
    }
}
//*/

为什么第一个有效而第二个无效?是关于操作顺序、布尔型强制转换为整数、运算符结合性还是OBOE的问题?

10
length()函数返回的是一个无符号类型吗? - Ben Voigt
1
不应该是 k + comments[i].length() < ? - changtung
@cyan:不,如果你从第一个循环条件两边减去 negwords[i].length(),你就得到了第二个条件。 - Ben Voigt
negwords和comments都是std :: vector <std :: string> - Matt G
1
通过正确的编译(例如,您应该至少使用-Wall来编译gcc),失败的代码应该会给您一个有关有符号和无符号整数之间比较的警告。 - Hagen von Eitzen
显示剩余3条评论
1个回答

33
如果negwords[j].length()comments[i].length()返回的无符号整数类型至少与unsigned int一样大,则k将被提升为相同的无符号类型,并且将应用模加法规则。
例如,这意味着1 < 2 - 3成立,因为在模算术中,2-3会被包装成一个非常大的数字。
如果您感兴趣,此行为在标准的第3.9.1节中指定,其中包括以下规则:
无符号整数应遵守模2 n 算术的规律,其中n是该特定大小的整数的值表示中的位数。
并涉及其影响的脚注:
48 这意味着无符号算术不会溢出,因为不能由结果无符号整数类型表示的结果将对可以由结果无符号整数类型表示的最大值加1取余。
数学家将这种算术称为Galois域的代数。在C ++中,它用于无符号整数类型。其他类型不使用模算术,但它们也不使用正常的小学算术(形式上为实数代数),因为正常的算术需要一个密集的不可数集合的数字,并且有限大小的计算机无法表示无限集合的成员。感谢Oliver指出我的错误。GF(2)^ n确实管辖位运算和一堆其他常见的计算机软件中的计算,例如CRC。但它不描述超过1位的无符号算术,因为Galois字段上的多项式不进行“进位”。

4
@Cyber: 不是下溢,而是DBL_MIN / 2.0 * 2.0等于零,这被称为环绕。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接