неподписанные и подписанные значения в C - PullRequest
2 голосов
/ 23 июля 2011

вот вопрос:

в книге «Компьютерные системы: взгляд программиста», раздел 2.2.5

сказано, что если значение без знака сравнивается со значением со знаком, все значения будут сравниваться в формате без символов. как это

if(-1 < 0u)
{
    // will not print this line because -1 will be translated to 255.
    printf("all changed to unsigned format");
}

Я попробовал этот код в VC6 SP6, строка НЕ ​​была выведена. И все выглядит хорошо, потому что мы все знаем, что -1 был переведен в 255.

но когда я читаю книгу «Эксперт C, Программирование Deep C Secrets», раздел 1.10

В нем сказано, что, если мой компилятор использует стандарт ANSI C, этот код выведет "-1 <(unsigned char) 1: ANSI": </p>

if(-1 < (unsigned char)1)
{
    printf("-1 < (unsigned char)1: ANSI");
}
else
{
    printf("-1 NOT Less than (unsigned char)1: K&R");    
}

Вывод, который я получил, был: -1 <(без знака) 1: ANSI. </p>

Я использую компилятор VC6 SP6.

и почему это происходит?

по книге «Компьютерные системы: взгляд программиста»

-1 <(unsigned char) 1 приведет к переводу -1 в качестве значения без знака. так оно и будет выглядеть так: </p>

255 <1 </p>

и это не должно выводить строку -1 <(unsigned char) 1: ANSI. </p>

Кто-нибудь может сказать мне, почему это происходит?

1 Ответ

12 голосов
/ 23 июля 2011

if(-1 < (unsigned char)1)

В этом случае оба операнда переводятся в int.

if( -1 < 0u )

В этом случае оба операнда преобразуются в unsigned int.

Следующие цитаты подтверждают мою правоту.

Многиебинарные операторы, которые ожидают операнды арифметического или перечислимого типа, вызывают преобразования и дают результаты типа аналогичным образом.Цель состоит в том, чтобы получить общий тип, который также является типом результата.Этот шаблон называется обычным арифметическим преобразованием, которое определяется следующим образом:
- Если один из операндов имеет тип long double, другой должен быть преобразован в long double.
- В противном случае, если один из операндов является двойным, другой должен быть преобразован в двойной.
- В противном случае, если один из операндов является float, другой должен быть преобразован в float.
- В противном случае интегральные преобразования (4.5) должны выполняться для обоих операндов. 54)
- Затем, если один из операндов является беззнаковым длинным, другой должен быть преобразован в беззнаковый длинный.
- В противном случае, если один операнд является длинным int, а другой - без знака int, то, если long int может представлять все значения без знака int, беззнаковое int должно быть преобразовано в long int;в противном случае оба операнда должны быть преобразованы в unsigned long int.
- В противном случае, если один из операндов длинный, другой преобразуется в длинный.
- В противном случае, если один из операндов не подписан, другой должен быть преобразован в беззнаковый.[Примечание: в противном случае единственным оставшимся случаем является то, что оба операнда являются целыми]

И это ( интегральные продвижения ):

Значение типа char, знака со знаком, знака без знака, короткого целого или без знака короткого целого типа int может быть преобразовано в значение типа int, если целое число может представлять все значения типа источника;в противном случае исходное значение r может быть преобразовано в значение типа unsigned int.

Чтобы быть совершенно честными, кавычки взяты из стандарта C ++ 03, но они также применимы и к C.

...