# V555. Expression of the 'A - B > 0' kind will work as 'A != B'.

Анализатор обнаружил потенциальную ошибку в выражении вида "A - B > 0". Высока вероятность, что условие написано неверно, если подвыражение "A - B" имеет беззнаковый тип.

Условие "A - B > 0" выполняется во всех случаях, когда значение 'A' не равно значению 'B'. Это значит, что вместо выражения "A - B > 0" можно написать "A != B". Но скорее всего программист задумывал совсем другое.

Рассмотрим пример:

    unsigned int *B;
    ...
    if (B[i]-70 > 0)

Программист хотел проверить, что i-тый элемент массива B больше значения 70. Это можно было записать так: "B[i] > 70". Исходя из каких-то своих соображений, программист записал эту проверку так: "B[i]-70 > 0". И допустил ошибку. Он забыл, что элементы массива 'B' имеют тип 'unsigned'. Это значит, что и выражение "B[i]-70" будет иметь тип 'unsigned'. Получается, что условие всегда истинно, за исключением случая, когда элемент 'B[i]' будет равен 70.

Поясним эту ситуацию.

Если 'B[i]' больше 70, то "B[i]-70" будет больше 0.

Если 'B[i]' меньше 70, то произойдет переполнение типа unsigned и мы получим очень большое значение. Пусть B[i] == 50. Тогда "B[i]-70" = 50u - 70u = 0xFFFFFFECu = 4294967276. Естественно, что 4294967276 > 0.

Демонстрационный пример:

    unsigned A;
    A = 10; cout << "A=10 " << (A-70 > 0) << endl;
    A = 70; cout << "A=70 " << (A-70 > 0) << endl;
    A = 90; cout << "A=90 " << (A-70 > 0) << endl;
    // Будет распечатано
    A=10 1
    A=70 0
    A=90 1

Первый вариант исправленного кода:

    unsigned int *B;
    ...
    if (B[i] > 70)

Второй вариант исправленного кода:

    int *B;
    ...
    if (B[i]-70 > 0)

Отметим, что выражение вида "A - B > 0" далеко не всегда означает наличие ошибки. Рассмотрим код, где анализатор выдаст ложное предупреждение:

    // Функции  GetLength() и GetPosition() возвращают
    // значение типа size_t.
    while ((inStream.GetLength() - inStream.GetPosition()) > 0)
    { ... }

Здесь GetLength() всегда больше или равно GetPosition(). Поэтому код корректен. Чтобы избавиться от ложного срабатывания можно использовать комментарий //-V555 или переписать код следующим образом:

    while (inStream.GetLength() != inStream.GetPosition())
    { ... }

Вот еще один случай, когда ошибки не возникнет.

    __int64 A;
    __uint32 B;
    ...
    if (A - B > 0)

Здесь подвыражение "A - B" имеет знаковый тип __int64 и ошибки не возникнет. Анализатор не выдает предупреждения в таких ситуациях.

Данная диагностика классифицируется как:

CWE-191 CERT-INT02-C

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V555.