GCC не предупреждает при использовании == op со знаком var и без знака литерала - PullRequest
8 голосов
/ 03 декабря 2010

Почему GCC предупреждает только о ситуациях 1 и 3, а не 2 в приведенном ниже коде?

Я компилирую с флагами -Wall и -g.

int main() {

    unsigned int ui = 4;
    int si = 6;

    if (si == ui ) { // Warning comparison b/w signed and unsigned
        printf("xxxx");
    }

    if (si == 2U ) { // No Warning --- WHY ???
        printf("xxxx");
    }

    if (si > 2U ) { // Warning comparison b/w signed and unsigned
        printf("xxxx");
    }

    return 0;
}

Ответы [ 3 ]

4 голосов
/ 03 декабря 2010

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html:

- секция преобразования:

Не предупреждать о явных приведениях типа abs ((int) x) и ui = (unsigned) -1, или если значение не изменяется при преобразовании, как в abs (2.0).

Поскольку 2U буквально, gcc знает, что:

  • если si < 0, то (unsigned) si >= 2^31, следовательно s1 != 2U.
  • если si > 0, то (unsigned) si имеет то же значение, что и si, поэтому (unsigned) si == 2U тогда и только тогда, когда si == 2.

В заключение, сравнение подписанного si с литералом 2U аналогично сравнению si с 2, т. Е. Результат si == 2U не будет изменен путем преобразования si в unsigned.

Если вы сравните с 2 ^ 32-1 (4294967295U), самым большим 32-битным целым без знака, который не представлен в int, тогда si может быть равно ему, даже если si отрицательно, это может быть не то, что вы хотели, поэтому предупреждение генерируется с опцией -Wextra.

1 голос
/ 03 декабря 2010

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

Если я поменяю его на

if (si == 2147483648U ) { printf("xxxx"); }

Я получаю предупреждение

(На самом деле мне пришлось добавить -Векстра, прежде чем я получил предупреждения, о которых вы сообщили)

0 голосов
/ 03 декабря 2010

Крис, спасибо за ваш ответ. Я думаю, что это приводит к делу. Моя первоначальная мысль заключалась в том, что суффикс U будет приводить к переводу этого литерала в тип без знака, однако я думаю, что он переводится в тип без знака, только когда число больше INT_MAX_32, то есть> 2147483647.

...