2012-04-06 5 views
1

Я пытаюсь вычесть два unsigned ints и сравнить результат с подписанным int (или литералом). При использовании типов unsigned int поведение будет таким, как ожидалось. При использовании uint16_t (от stdint.h) типы поведения не то, что я ожидал бы. Сравнение проводилось с использованием gcc 4.5.
Учитывая следующий код:C: uint16_t поведение вычитания в gcc

unsigned int a; 
unsigned int b; 

a = 5; 
b = 20; 

printf("%u\n", (a-b) < 10); 

Выход равен 0, что то, что я ожидал. Оба а и Ь без знака, и б больше, чем, так что результат является крупным беззнаковое число, которое больше 10. Теперь, если я изменить а и б к типу uint16_t:

uint16_t a; 
uint16_t b; 

a = 5; 
b = 20; 

printf("%u\n", (a-b) < 10); 

Выход 1 . Почему это? Является результатом вычитания двух типов uint16_t, хранящихся в int в gcc? Если я изменю 10 на 10U, то результат снова будет 0, что, кажется, поддерживает это (если результат вычитания сохраняется как int, а сравнение производится против unsigned int, а результаты вычитания будут преобразованы в unsigned int).

+0

Результат не просто «хранится в int». Все вычитание выполняется как 'int' вычитание, то есть оба операнда uint16_t' преобразуются в' int', прежде чем вычитание даже имеет шанс начать. интегральные рекламные акции. – AnT

ответ

6

Поскольку вычисления не выполняются с типами ниже int/unsigned int (char, short, unsigned short и т. Д., Но не длинными, unsigned long и т. Д.), Но они сначала повышаются до одного из int или unsigned int. «uint16_t», возможно, «unsigned short» для вашей реализации, что повышается до «int» в вашей реализации. Таким образом, результат этого вычисления тогда равен «-15», который меньше 10.

В старых реализациях, которые вычисляют с 16 бит, «int» может быть не в состоянии представить все значения «unsigned short», потому что оба имеют одна и та же битовая ширина. Такие реализации должны способствовать «unsigned short» для «unsigned int». В таких реализациях ваше сравнение приводит к «0».

3

Перед оба - и < операций выполняются, набор преобразований называют обычных арифметических преобразований применяется для преобразования операндов к общему типу. В рамках этого процесса применяются целые рекламные акции, которые продвигают типы, более узкие, чем int или unsigned int, одному из этих двух типов.

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

Во втором случае очевидно, что при вашей реализации тип int может содержать все значения типа uint16_t. Это означает, что при применении целочисленных рекламных акций значения a и b повышаются до типа int. Вычитание выполняется, что приводит к значению -15 с типом int. Оба операнда для < уже являются int, поэтому никаких преобразований не выполняется; результатом < является 1.

При использовании 10U в последнем случае результат a - b еще -15 с типом int. Однако теперь обычные арифметические преобразования приводят к преобразованию этого значения в unsigned int (так же, как в первом примере было 10), что приводит к значению UINT_MAX - 14; результатом < является 0.

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

  • Нет связанных вопросов^_^