преобразование 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.