преобразование int в short в C
Я:
int a = 2147483647;
short b = (short)a;
и я b = -1
тогда как я ожидаю int32
для преобразования в int16
(short
). Я ожидаю увидеть некоторую ценность и не -1
.
пожалуйста, кто-нибудь, помогите мне с этим.
5 ответов
ваш int A больше, чем размер short. Когда вы преобразуете A в short, вы получаете 1 в левом самом бит, что будет означать, что это отрицательное число. Поскольку вы получаете -1, Я полагаю, вы получаете 1s во всех 16 битах, что даст вам -2^15 + 2^14 + 2^13... + 2^0, что даст вам -1. Короче говоря (без каламбура), вы не можете преобразовать целое число в короткое, если оно слишком велико.
значение 2147483647, или 231-1 переполнения 16-разрядное целое число. Его двоичное представление равно нулю в MSB, за которым следует 31 в оставшихся битах.
похоже, что в вашей реализации последние 16 бит берутся в преобразовании в short
. Когда это происходит, все они настроены на 1
, в результате 2-х!--10--> представление -1
:
32-bit int: 01111111111111111111111111111111
16-bit short: ----------------1111111111111111
однако, ни 2-комплимент представление, ни это поведение в целом является частью стандарта C++, поэтому такое поведение определяется реализацией.
преобразование значения к подпись type, если исходное значение не соответствует целевому типу, дайте реализация-определено результат. Это означает, что любая соответствующая документация компилятора должна документировать этот результат.
(это не похоже на поведение при переполнении арифметического оператора. Например:
int overflow = INT_MAX + 1;
фактически неопределенное поведение. Но в любом случае, вы должны быть осторожны, чтобы напишите свой код, чтобы он не вызывал такого рода проблемы.)
для многих реализаций, как для преобразования, так и для арифметики, переполнение, где целью является N-разрядный тип, просто принимает N битов низкого порядка правильного результата.
в вашем случае, видимо int
32 бита и short
составляет 16 бит (эти размеры могут варьироваться в разных реализациях). 2147483647
is 0x7fffffff
, младшие 16 бит 0xffff
, который (опять же, на ваши воплощения) представление -1
тип short
.
для преобразования в неподписанные типы результат строго определяется стандартом; он принимает N битов низкого порядка результата. И для переполнения преобразования с плавающей запятой (скажем, преобразование очень большого double
значение float
), поведение не определено.
пока это все равно для C и c++. Но чтобы добавить к путанице, начиная со стандарта 1999 года переполнение подписанного преобразования разрешено поднимать сигнал, определенный реализацией. C++ не имеют. Я не знаю ни одного компилятора, который действительно это делает.
я ожидаю увидеть некоторое значение и не
-1
.
-1
is "ценности". Вы ожидали какой-то особой ценности?
кстати:
short b = (short)a;
бросок не нужен. Назначение, инициализация, передача параметров и return
операторы могут назначать значения между любыми числовыми типами без приведения. Значение преобразуется неявно:
short b = a;
это implementation defined
поведение, например gcc
Integers Implementation document
говорит:
для преобразования в тип ширины N значение равно уменьшено по модулю 2^N, чтобы быть в пределах диапазона типа; сигнал не поднимается.
это может отличаться от компилятора к компилятору, я не могу выкопать подобные документы для clang
, ни visual studio
.
из проекта стандарта C++ раздел 4.7 Integral conversions
пункт 3
:
если целевой тип подписан, значение остается неизменным, если оно может быть представлено в целевой тип (и бит-ширина поля); в противном случае значение определяется реализацией.
если бы это было unsigned
тогда у вас было бы совершенно определенное поведение, согласно параграфу 2
:
если целевой тип подписан, полученное значение наименьшее беззнаковое целое конгруэнтна исходное целое число (по модулю 2n, где n-количество битов, используемых для представления типа без знака). [ Примечание: в дополнительном представлении двойки это преобразование является концептуальным, и в битовом шаблоне нет изменений (если нет усечения). - конец Примечания ]
язык похож на C99
проект стандарта раздел 6.3.1.3 Signed and unsigned integers
.
вы можете сделать это:
uint32_t sum=0xFFFF1234;
uint16_t *p= (uint16_t *) ∑
uint16_t checksum=p[0];
чек-сумма 0x1234
.
вот еще один способ:
union ToShort
{
uint32_t sum;
uint16_t checksum[2];
} toShort;
toShort.sum=0xFFFF1234;
cout << hex << toShort.checksum[0];
выход 1234
.