1

Вопрос по gcc, c – C: поведение вычитания uint16_t в gcc

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

unsigned int a;
unsigned int b;

a = 5;
b = 20;

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

Выход 0, что я и ожидал. И a, и b не имеют знака, а b больше, чем a, поэтому в результате получается большое число без знака, которое больше 10. Теперь, если я изменю a и b на тип 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". Все вычитание выполняется какint вычитание, то есть обаuint16_t операнды преобразуются вint прежде чем вычитание даже имеет шанс начать. Читайте об интегральных акциях.

    от AnT
  • 6

    Поскольку вычисления не выполняются с типами ниже int / unsigned int (

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

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

  • 3

    Перед тем как

    - а также< Операции выполняются, набор преобразований называетсяusual arithmetic conversions применяются для преобразования операндов в общий тип. В рамках этого процессаinteger promotions применяются, которые продвигают типы более узкие, чем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.