С++, похоже, нарушает свойства сложения

Работая над назначением для класса, я столкнулся с этим (обратите внимание на условие цикла)

// 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++;
    }
}
//*/

Почему первый работает, а второй - нет? Это что-то о порядке операций, bool-принуждении к int, операторной ассоциативности или OBOE?

Ответ 1

Если либо negwords[j].length(), либо comments[i].length() возвращает целочисленный тип без знака, как минимум равный unsigned int, тогда k будет продвигаться к тому же неподписанному типу, а будут применяться правила модульного добавления.

В качестве примера это означает, что 1 < 2 - 3 истинно, потому что 2 - 3 обертывается в модульной арифметике, становясь очень большим числом.

Если вас это интересует, это поведение указано в разделе 3.9.1 Стандарта, которое включает правило:

Незнакомые целые числа должны подчиняться законам арифметики по модулю 2 n где n - количество бит в представлении значений этого конкретного размера целых чисел.

И сноска о последствиях:

48 Это означает, что беззнаковая арифметика не переполняется, потому что результат, который не может быть представлен результирующим целым типом без знака, уменьшается по модулю число, которое больше одного наибольшего значения, которое может быть представлено результирующий целочисленный тип без знака.


Математики знают этот тип арифметики как алгебру полей Галуа. В С++ он используется для неподписанных типов интегралов. Другие типы не используют модульную арифметику, но они также не используют обычную арифметику средней школы (формально, алгебра действительных чисел), потому что для нормальной арифметики требуется плотный несчетный набор чисел, а компьютер конечных размер не может представлять элементы бесконечного множества.

Спасибо Оливеру за то, что он указал на мою ошибку. GF (2) ^ n управляет поразрядными операциями и целым рядом других общих вычислений, выполненных в компьютерном программном обеспечении, таких как CRC. Но он не описывает беззначную арифметику более 1 бит, так как многочлены на полях Галуа не "несут".