Вам необходимо изучить работу операторов в правилах C и C продвижения и преобразования.Они объясняются в стандарте C. Некоторые выдержки из него, плюс мои комментарии:
6.5.8 Реляционные операторы
Синтаксис
1 реляционная выражение:
сдвиг выражения
реляционного выражения < сдвиг выражение
реляционного выражения > сдвиговое выражение
реляционное выражение < = сдвиг-выражение
relational-expression> = shift-expression
Семантика
3 Если оба операнда имеют арифметический тип, обычные арифметические преобразования выполняются.
Большинство операторов включают в себя это «обычное арифметическое преобразование» перед действительной операцией (добавление, умножение, сравнение и т. Д. И т. Д.).- Alex
6.3.1.8 Обычные арифметические преобразования
1 Многие операторы, которые ожидают операнды преобразования вызывают арифметического типа и результат текучести типов аналогичным образом. Цель состоит в том, чтобы определить общий реальный тип для операндов и результат. Для указанных операндов каждый операнд преобразуется без изменения типа домена к типу, соответствующий реальный тип которого является общим реальным типом. Если явно указано иначе, общий реальный тип также является соответствующим реальным типом результат, домен типа которого является доменом типа операндов, если они являются одинаковыми, и сложным в противном случае. Эта модель называется обычные арифметические преобразования:
Во-первых, если соответствующий реальный тип любого операнда имеет длину двойной, а другой операнд преобразуется, без изменения домена типа, к типу которого соответствующие реальным тип длинный двойной.
В противном случае, если соответствующий реальный тип любого операнда вдвое, а другой операнд преобразуется без изменения домена типа, к типу которого соответствующий реальный тип вдвое.
В противном случае, если соответствующий реальный тип любого операнда с плавающей точкой, а другой операнд преобразуется без изменения домена типа, к типу которого соответствующий вещественный тип с плавающей точкой.
В противном случае целые акции выполняются в обоих операндах. Затем к продвинутым операндам применяются следующие правила:
Если оба операнда имеют один и тот же тип, то дальнейшее преобразование не требуется.
В противном случае, если оба операнда подписали целочисленные типы или оба имеют неподписанные целочисленных типов, операнд с типом меньшего ранга целочисленного преобразования является преобразуется к типу операнда с большим рангом.
В противном случае, если операнд, который имеет беззнаковый целое число типа имеет ранг больше или равный ранг типа другого операнда, то операнд с знаковым целочисленным типа преобразуется к типу операнда с беззнаковым целочисленный тип.
В противном случае, если тип операнда с подписью целочисленного типа может представлять все значения типа операнда с целым числом без знака типа, то операнда с целым числом без знака типа преобразуются в тип операнд со знаком целого типа.
В противном случае оба операнда преобразуются в целое число без знака , соответствующее типу операнда со знаком целочисленного типа.
6.3.1.3 Подписанные и целые числа без знака
Когда значение с целочисленным типом преобразуется в другой целочисленный тип, кроме _Bool, если значение может быть представлено нового типа, он не изменился.
В противном случае, если новый тип без знака, значение преобразуется путем многократного добавления или вычитания больше, чем максимальное значение, которое может быть представлено в новом типе , пока значение не находится в пределах нового типа один , (Правила описывают арифметику по математическому значению, а не значение данного типа выражения.)
В противном случае новый тип подписан и значение не может быть представлено в нем; либо результат определяется реализацией или повышается сигнал, определяемый реализацией.
Таким образом, в вашем a>b
(с a
будучи 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.
Хорошо прочитано для всех http://www.a-coding.com/2010/12/beware-usigned-integers.html – Krishnabhadra