C переполнение целочисленного типа при присваивании целым числам большей ширины - PullRequest
7 голосов
/ 08 апреля 2009

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

#include <stdint.h>

uint16_t a = 4000;
uint16_t b = 8000;

int32_t c = a - b;

printf("%d", c);

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

Ответы [ 4 ]

5 голосов
/ 08 апреля 2009

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

3 голосов
/ 08 апреля 2009

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

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

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

1 голос
/ 08 апреля 2009

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

0 голосов
/ 08 апреля 2009

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

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

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

...