Преобразовать unsigned int в подписанный int C
Я пытаюсь преобразовать 65529
из unsigned int
в подписанный int
. Я пробовал делать такие роли:
unsigned int x = 65529;
int y = (int) x;
Но y
все еще возвращает 65529, когда он должен вернуться -7. Почему это?
Ответы
Ответ 1
Кажется, вы ожидаете, что int
и unsigned int
будут 16-разрядным целым числом. Это, очевидно, не так. Скорее всего, это 32-битное целое число, которое достаточно велико, чтобы избежать ожидаемого переноса.
Обратите внимание на то, что для этого не существует полностью совместимого с C способа, потому что литье между подписанными/неподписанными значениями вне диапазона определяется реализацией. Но это будет работать в большинстве случаев:
unsigned int x = 65529;
int y = (short) x; // If short is a 16-bit integer.
или, альтернативно:
unsigned int x = 65529;
int y = (int16_t) x; // This is defined in <stdint.h>
Ответ 2
Я знаю, это старый вопрос, но он хороший, так как насчет этого?
unsigned short int x = 65529U;
short int y = *(short int*)&x;
printf("%d\n", y);
Ответ 3
@Mysticial получил его. Короткий, как правило, 16-бит и иллюстрирует ответ:
int main()
{
unsigned int x = 65529;
int y = (int) x;
printf("%d\n", y);
unsigned short z = 65529;
short zz = (short)z;
printf("%d\n", zz);
}
65529
-7
Press any key to continue . . .
Немного более подробно. Это все о том, как подписанные числа хранятся в памяти. Сделайте поиск для двухкомпонентной нотации более подробно, но вот основные сведения.
Итак, давайте посмотрим на 65529 десятичных знаков. Его можно представить как FFF9h
в шестнадцатеричном формате. Мы также можем представить, что в двоичном формате:
11111111 11111001
Когда мы объявляем short zz = 65529;
, компилятор интерпретирует 65529 как знаковое значение. В двухзадачной нотации верхний бит означает, что значение знака положительное или отрицательное. В этом случае вы можете видеть, что верхний бит является 1
, поэтому он рассматривается как отрицательное число. Вот почему он печатает -7
.
При значении unsigned short
нам не нужен знак, так как он unsigned
. Поэтому, когда мы печатаем его с помощью %d
, мы используем все 16 бит, поэтому он интерпретируется как 65529
.
Ответ 4
Представление значений 65529u и -7 идентично для 16-битных ints. Только интерпретация бит отличается.
Для больших значений и этих значений вам нужно подписать расширение; один путь с логическими операциями
int y = (int )(x | 0xffff0000u); // assumes 16 to 32 extension, x is > 32767
Если скорость не является проблемой или разделить на процессор быстро,
int y = ((int ) (x * 65536u)) / 65536;
Умножьте сдвиги на оставшиеся 16 бит (опять же, предполагая расширение от 16 до 32), а разделитель сдвигается вправо, сохраняя знак.
Ответ 5
Чтобы понять, почему, вам нужно знать, что ЦП представляет собой подписанные числа, используя два дополнения (возможно, не все, но многие).
byte n = 1; //0000 0001 = 1
n = ~n + 1; //1111 1110 + 0000 0001 = 1111 1111 = -1
А также, что тип int и unsigned int могут быть разного размера в зависимости от вашего процессора. Когда вы делаете такие вещи, как это:
#include <stdint.h>
int8_t ibyte;
uint8_t ubyte;
int16_t iword;
//......
Ответ 6
Вы ожидаете, что ваш тип int
имеет ширину 16 бит, и в этом случае вы действительно получите отрицательное значение. Но, скорее всего, это 32 бита в ширину, поэтому подписанный int
может отлично отображать 65529. Вы можете проверить это, напечатав sizeof(int)
.
Ответ 7
Чтобы ответить на вопрос, опубликованный в комментарии выше, попробуйте что-то вроде этого:
unsigned short int x = 65529U;
short int y = (short int)x;
printf("%d\n", y);
или
unsigned short int x = 65529U;
short int y = 0;
memcpy(&y, &x, sizeof(short int);
printf("%d\n", y);