2009-06-18 3 views
4

В нижнем кодовом блоке ниже показано, что происходит с неявным преобразованием, которое имеет место в выражении if для 7? Я бы получил хотя бы (0x98 < = 0x07), но это не то, что происходит, когда условие оценивается как true и вызывает вызов DoMyStuff.C сравнение char и int

char minstogo = 0x98; 
if(minstogo <= 7) { 
    DoMyStuff(); 
} 

ответ

15

Всякий раз, когда у вас есть бинарный оператор (один из +-*/%<<>>&|^==!=<<=>>=) между двумя целыми операндами разных типов, два типа преобразуются к общему типу перед операцией выполняется. Правила принятия решения о преобразованном типе (из раздела 6.3.1.8 стандарта C99):

Если оба операнда имеют один и тот же тип, то дальнейшие преобразования не требуются.

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

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

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

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

В этом случае char может быть либо целым типом подписанного, либо без знака - его подпись определяется реализацией. К счастью, хотя int может представлять все возможные значения char, независимо от того, подписан или нет char, если вы находитесь в системе, где char s - 8 бит, а int s - не менее 16 бит.

Если char подписан, то второй пункт выше относится, так что оба операнд преобразуется в int (типа с более высоким рангом, ранг определяется в несколько сложном образе, но это по существу эквивалентно битового размер типа). Так как 0x98, так как подписанный char, отрицательный, он преобразуется в целое число -104, который затем меньше 7.

Если вместо char не подписан, то четвертый пункт применяется вместо этого. Без знака char будет преобразован в 152 как int, что больше, чем 7.

Никогда не полагаться на char s будучи знаком или без знака. Если вам нужны 8-битные целые числа с определенной подписью, используйте явно signed char или unsigned char или используйте типы C99 int8_t и uint8_t, определенные int <stdint.h>.

Очень легко укусить тонкие ошибки, вызванные целыми правилами продвижения. Я настоятельно рекомендую вам всегда компилировать с помощью -Wall с gcc, который предупредит вас о сравнении целых чисел, подписанных и без знака, которые часто являются причиной ошибок.

6

Что, вероятно, происходит в том, что символ является знаковое значение и 0x98, следовательно, регистрации в качестве отрицательного числа. Следовательно, он меньше 7

Также в этом случае 7 не будет конвертироваться. Вместо этого символ будет расширен до того же интегрального типа, что и 7, и тогда будет проведено сравнение.

0

Используя ваш компилятор с его текущими настройками, char является подписанным типом: и поскольку установлен бит высокого порядка (0x80) его значения, это значение отрицательное. Когда minstogo расширяется, что отрицательный знак сохраняется (через знак-расширения), и так minstogo расширяется до отрицательного целого числа (например, 0xFF98), что меньше, чем 7.

+3

У этого есть определенный определенный реализацией знак. Иногда он подписывается (на некоторых хостах), иногда (на других хостах) это не так. –

+1

Независимо от того, подписан ли символ или неподписанный, зависит от платформы, компилятора и конфигурации; например, PowerPC ABI предлагает, чтобы char был непознан, а GCC принимает переопределения параметров -fsigned-char'/'-funsigned-char' для переопределения значений по умолчанию для платформы. Портативный код не должен полагаться на (un) подпись char. – ephemient

+0

Компилятор OP обрабатывает свой символ как подписанный. – ChrisW

0

0x98 является 152.

С вы объявили «char», а не «unsigned char», вы пытаетесь присвоить 152 типу, который имеет диапазон -128 - 127.

Это будет переполнение и даст вам отрицательное число, которое будет < 7 (0x07).

1

С символами, представленными в виде восьмибитного байта, установка minstogo на 0x98 является двоичным значением 10011000. Знаковый бит установлен, это отрицательное целочисленное значение. Вероятно, вам нужен символ unsigned, чтобы тест мог оценить false.

1

Он оценит такой же, как 0x98 <= 7 исключением случаев, когда char по умолчанию типа платформы в подписанному и CHAR_BIT равно 8. В этом случае значение minstogo будет отрицательным и minstogo <= 7 будет истинным.