Основное целочисленное назначение

Вот что вызывает у меня разочарование:

У нас есть два целых числа: один имеет тип 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).