C ++: несоответствие со знаком / без знака при использовании только неподписанных типов - PullRequest
5 голосов
/ 19 декабря 2011

Когда я пытаюсь скомпилировать следующую программу C ++ с использованием компилятора Visual Studio 2010 C ++ (X86) с включенным уровнем предупреждения / W4, я получаю предупреждение о несоответствии со знаком / без знака в отмеченной строке.

#include <cstdio>
#include <cstdint>
#include <cstddef>

int main(int argc, char **argv)
{
    size_t idx = 42;
    uint8_t bytesCount = 20;

    // warning C4389: '==' : signed/unsigned mismatch
    if (bytesCount + 1 == idx)
    {
        printf("Hello World\n");
    }

    // no warning
    if (bytesCount == idx)
    {
        printf("Hello World\n");
    }
}

Это смущает меня, так как я использую только неподписанные типы.Поскольку сравнение

bytesCount == idx

не вызывает такого предупреждения, оно, вероятно, связано с каким-то странным неявным разговором, который происходит здесь.

Таким образом: в чем причина, почему я получаю это предупреждение ипо каким правилам происходит этот разговор (если это причина)?

Ответы [ 4 ]

9 голосов
/ 19 декабря 2011

1 - подписанный литерал.Попробуйте bytesCount + 1U.

Компилятор, вероятно, создает временное значение типа со знаком из-за добавления значений со знаком и без знака (bytesCount + 1)

5 голосов
/ 19 декабря 2011

1 является int. Тип интегрального арифметического выражения зависит от используемых типов. В этом случае у вас есть тип unsigned и тип signed, где тип unsigned меньше, чем тип signed. Это подпадает под стандарт C ++ для выражений (раздел 5.10 [expr]):

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

Т.е. тип выражения bytesCount + 1 равен int, который подписан по умолчанию.

3 голосов
/ 19 декабря 2011

Поскольку 1 имеет тип int, выражение bytesCount + 1 равно int (подписано).

Фактически, когда в математическом выражении используется тип, меньший int, он повышается доint, поэтому даже + bytesCount и bytesCount + bytesCount считаются int, а не uint8_t (тогда как bytesCount + 1U является unsigned int, поскольку оно на больше , чем int).

следующая программа выводит true три раза.

#include <iostream>

int main() 
{
    unsigned short s = 1;
    std::cout << (&typeid( s + 1U ) == &typeid(1U)) << std::endl;
    std::cout << (&typeid( + s ) == &typeid(1)) << std::endl;
    std::cout << (&typeid( s + s ) == &typeid(1)) << std::endl;
}
1 голос
/ 19 декабря 2011

Другие ответы уже говорят вам, что bytesCount + 1 интерпретируется как signed int. Тем не менее, я хотел бы добавить, что в bytesCount == idx, bytesCount равно и интерпретируется как signed int. Концептуально, он сначала конвертируется в signed int, а после этого конвертируется только в unsigned int Ваш компилятор не предупреждает об этом, потому что у него достаточно информации, чтобы понять, что в действительности проблемы нет. Преобразование в signed int не может сделать bytesCount отрицательным. Сравнение bytesCount + 1 одинаково верно, одинаково безопасно, но немного сложнее, чтобы компилятор больше не распознавал его как безопасный.

...