2012-04-20 4 views
0

Можно создать дубликат:
Arithmetic operations on unsigned and signed integersбез знака и INT Гоча

unsigned int b=2; 
int a=-2; 

if(a>b) 
    printf("a>b"); 
else 
    printf("b>a"); 

ВЫВОД: а> Ь

int b=2; 
int a=-2; 

if(a>b) 
    printf("a>b"); 
else 
    printf("b>a"); 

ВЫВОД: Ь> а

ПОЖАЛУЙСТА, кто-то объяснить выход

+0

Хорошо прочитано для всех http://www.a-coding.com/2010/12/beware-usigned-integers.html – Krishnabhadra

ответ

1

В первом случае оба операнда преобразуются в unsigned int, преобразованное a будет UINT_MAX-1, что намного больше чем b и, следовательно, на выходе.

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

+2

Что делает '-1' преобразуется в' '' '' '' to 'UINT_MAX '? –

0

От The C Programming Language от Kernighan и Ritchie - 2.7 Type Conversions - стр. 44; вторая половина страницы подробно описывает тот же сценарий. Небольшая часть ниже для вашей справки.

Правила преобразования сложны, когда задействованы операнды unsigned. Проблема в том, что сравнение значений signed и unsigned зависит от машины, поскольку они зависят от размеров различных типов integer. Например, предположим, что int имеет длину 16 бит, а long - 32 бита. Затем -1L < 1U, потому что 1U, что составляет int, составляет signed long. Но -1L > 1UL, потому что -1L - unsigned long и, следовательно, похожее на большее положительное число.

+0

Хотя в целом, в данном случае это относительно прямолинейно; оба типа имеют одинаковый размер 'int', хотя один -' signed' и другой 'unsigned'. –

-2

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

Число преобразований типа между подписанными и неподписанными типами может иметь одинаковый ранг на C99. Это когда неподписанные и подписанные типы имеют соответствующие типы, когда это происходит, результат зависит от компилятора.

Here is a summary of the rules.

+1

Быть тупым, но точным: это неправильно. –

+0

[ссылка] (https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+ Понимать + целое + преобразование + правила) Ранг любого целых чисел без знака равен рану соответствующего знакового целочисленного типа, если таковой имеется. – Balp

+0

Ключевое (нет, важно) слово «соответствующее», как правило, отсутствует в вашем ответе. «Конвертировать ионы», вероятно, должно быть «конверсией». В задаче, заданной в вопросе, нет зависимости от компилятора; он полностью определяется стандартом C. (И, для записи, я не проголосовал за вас, по крайней мере, еще нет.) Вы можете и должны отредактировать свой ответ, чтобы спасти его. Например, вы можете добавить свою ссылку на ответ. –

0

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

Ну, отрицательные числа имеют много старших биты, установленные ...

Поскольку ваши операнды все тот же ранг, это просто вопрос неподписанных битовые комбинаций сравниваемый.

И так -2 представлен 111111..110, один меньше максимально возможного, и он легко бьет 2 при интерпретации без знака.

0

Вам необходимо изучить работу операторов в правилах C и C продвижения и преобразования.Они объясняются в стандарте C. Некоторые выдержки из него, плюс мои комментарии:

6.5.8 Реляционные операторы
Синтаксис
1 реляционная выражение:
сдвиг выражения
реляционного выражения < сдвиг выражение
реляционного выражения > сдвиговое выражение
реляционное выражение < = сдвиг-выражение
relational-expression> = shift-expression

Семантика
3 Если оба операнда имеют арифметический тип, обычные арифметические преобразования выполняются.

Большинство операторов включают в себя это «обычное арифметическое преобразование» перед действительной операцией (добавление, умножение, сравнение и т. Д. И т. Д.).- Alex

6.3.1.8 Обычные арифметические преобразования

1 Многие операторы, которые ожидают операнды преобразования вызывают арифметического типа и результат текучести типов аналогичным образом. Цель состоит в том, чтобы определить общий реальный тип для операндов и результат. Для указанных операндов каждый операнд преобразуется без изменения типа домена к типу, соответствующий реальный тип которого является общим реальным типом. Если явно указано иначе, общий реальный тип также является соответствующим реальным типом результат, домен типа которого является доменом типа операндов, если они являются одинаковыми, и сложным в противном случае. Эта модель называется обычные арифметические преобразования:

  • Во-первых, если соответствующий реальный тип любого операнда имеет длину двойной, а другой операнд преобразуется, без изменения домена типа, к типу которого соответствующие реальным тип длинный двойной.

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

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

  • В противном случае целые акции выполняются в обоих операндах. Затем к продвинутым операндам применяются следующие правила:

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

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

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

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

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

6.3.1.3 Подписанные и целые числа без знака

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

  2. В противном случае, если новый тип без знака, значение преобразуется путем многократного добавления или вычитания больше, чем максимальное значение, которое может быть представлено в новом типе , пока значение не находится в пределах нового типа один , (Правила описывают арифметику по математическому значению, а не значение данного типа выражения.)

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

Таким образом, в вашем a>ba будучи int и b будучи unsigned int), согласно вышеуказанным правилам вы получаете a преобразуются в unsigned int перед сравнением. Так как a отрицательный (-2), значение без знака становится UINT_MAX+1+a (это бит repeatedly adding or subtracting one more than the maximum value). И UINT_MAX+1+a в вашем случае UINT_MAX+1-2 = UINT_MAX-1, что является огромным положительным числом по сравнению со значением b (2). И поэтому a>b дает «true».

Забудьте математику, которую вы узнали в школе. Узнайте, как это делает C.

Смежные вопросы