Поведение целочисленного переполнения C при присвоении целым числам большей ширины

StackOverflow https://stackoverflow.com/questions/728847

Вопрос

Если я выполню следующий код на C:

#include <stdint.h>

uint16_t a = 4000;
uint16_t b = 8000;

int32_t c = a - b;

printf("%d", c);

В результате он правильно печатает «-4000».Однако я немного в замешательстве:не должно ли быть арифметического переполнения при вычитании большего целого числа без знака из другого?Какие правила кастинга здесь действуют?Этот вопрос кажется немного нубским, поэтому любые ссылки будут очень признательны.

Это было полезно?

Решение

На самом деле вопрос несколько сложный.Операнды арифметических выражений преобразуются по особым правилам, которые вы можете увидеть в разделе 3.2.1.5 руководства. Стандартный (C89).В вашем случае ответ зависит от типа uint16_t является.Если оно меньше int, сказать short int, то операнды преобразуются в int и вы получите -4000, но на 16-битной системе, uint16_t может быть unsigned int и преобразование в подписанный тип не произойдет автоматически.

Другие советы

Короткий ответ: все они повышены до int во время вычитания.Подробный ответ см. в разделе 6.3.1.1 руководства. Стандарт С, где говорится о целочисленные акции в арифметических выражениях.Соответствующий язык из стандарта:

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

Детали тоже есть, но они довольно неприятные.

Оба операнда повышаются до int32_t во время вычитания.Если бы результат был больше максимального значения для int32_t вы бы увидели переполнение.

На самом деле переполнение есть, но C вам об этом не сообщает.

Переполнение оставляет значение, которое оказывается равным -4000, если интерпретировать его как целое число со знаком.Это работает так, как задумано на машинах с двумя комплементами.

Попробуйте интерпретировать результат как беззнаковый, и вы заметите, что (u1-u2) оценивается каким-то, казалось бы, несвязанным числом, когда u1 < u2.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top