Основное целочисленное назначение
Вот что вызывает у меня разочарование:
У нас есть два целых числа: один имеет тип int16_t
, а другой - int8_t
. Я инициализировал обе переменные следующим образом:
int8_t short_int = 250 //This equals -6, and its binary representation is 0b1111 1010
Пока все хорошо.
int16_t my_int = short_int //as we already know short_int is 0b1111 1010
Для меня my_int должен равняться 0b1111 1010 правильно? В качестве 16-битного целого значения
0b1111 1010 имеет десятичное представление 250. ОК, но это не так.
Распечатка значения my_int Я получаю -6, который в двоичном представлении равен 0b1111 1111 1111 1010 полностью отличается от short_int
как двоичный файл.
Ответы
Ответ 1
int8_t short_int = 250
вызывает поведение, определяемое реализацией. Диапазон int8_t
составляет -128
через 127
.
Очевидно, ваша реализация генерирует значение -6
для short_int
здесь. До сих пор.
Но теперь вы должны помнить, что C имеет значения, сохраняющие конверсии. Если вы конвертируете -6
в любой другой тип подписанного интеграла, он все равно будет -6
, независимо от его битового представления.
Некоторые люди расскажут о "расширении знака" и других подобных материалах, однако, чтобы понять, как работает C, вы просто должны помнить, что значение сохраняется, если оно не находится за пределами диапазона для типа; в этом случае он либо усечен (для неподписанных типов), либо определяется поведением (для подписанных типов, обычно с усечением 2-х частей).
Ответ 2
C работает на основе значений не по битовым образцам.
Если вы назначаете int8_t
для int16_t
, оба значения имеют одинаковое значение после этого.
Для отрицательных значений это означает, что у них есть другой битовый шаблон (при условии общего представления отрицательных значений).
Обратите внимание, что ваш int8_t
на самом деле отрицательный.
Ответ 3
Использование:
int16_t my_int = (uint8_t) short_int;
вместо:
int16_t my_int = short_int;
short_int
- отрицательное целое число со знаком, поэтому при преобразовании в int16_t
оно претерпевает расширение знака.
Ответ 4
Стандарт говорит
C11: 7.20.1.1
Имя typedef
intN_t
обозначает целочисленный тип со знаком с шириной N
, без битов дополнений и двухкомпонентное представление. Таким образом, int8_t
обозначает тип signed integer
с шириной ровно 8
бит.
При назначении short_int
- my_int
количество битов его двоичного представления увеличивается, сохраняя знак short_int
и значение (его называемое "расширением знака" ).
short_int
является отрицательным, и поэтому my_int
будет иметь один и тот же знак с одинаковым значением, но с некоторыми добавленными битами.
Ответ 5
Ответ на ungur_gongor правильный. Если вы действительно хотите получить доступ к битовой схеме, как если бы она была int8_t
или int16_t
, вы можете использовать union
:
union {
int8_t short_int;
int16_t my_int;
} converter;
converter.my_int = 0;
converter.short_int = 250;
printf("%d\n", converter.my_int);
Остерегайтесь, однако, выравнивания (где есть пробел для int8_t
?) и endianness int16_t
.
Это сохранит битовый шаблон (а не значение), хотя, вероятно, только в байте, который покрывает short_int
(вот почему я сначала установил my_int
в 0).