Сужающее преобразование в C++

В Руководстве Биджа по сетевому программированию есть функция, призванная обеспечить переносимый способ сериализации 16-битного целого числа.

/*
** packi16() -- store a 16-bit int into a char buffer (like htons())
*/ 
void packi16(unsigned char *buf, unsigned int i)
{
    *buf++ = i>>8; *buf++ = i;
}

Я не понимаю, почему заявление *buf++ = i; является переносимым, как присвоение целого числа без знака (i) без знака (*buf) приведет к сужению конверсии.

  • Гарантирует ли стандарт C++, что при таком преобразовании unsigned int всегда обрезается, и его младшие 8 бит сохраняются в unsigned char?
  • Если нет, есть ли какой-либо предпочтительный способ решить проблему? Достаточно ли изменить тело функции на следующее?

    * buf ++ = (i >> 8) & 0xFFFFU; * buf ++ = i & 0xFFFFU;

2 ответа

Решение

Код предполагает 8-битный байт, и он не является переносимым.

Например, некоторые цифровые сигнальные процессоры Texas Instruments имеют 16-битный байт.

Количество бит на байт определяется как CHAR_BIT от <limits.h>,

Кроме того, код предполагает, что unsigned 16 бит, который не является переносимым.

Таким образом, код не является переносимым.


ре

Гарантирует ли стандарт C++, что в таком преобразовании беззнаковое int всегда усекается, а его младшие 8 бит сохраняются в беззнаковом символе?

Нет, поскольку стандарт C++ не гарантирует, что число битов в байте равно 8.

Единственная гарантия - это как минимум 8 бит.

Арифметика без знака гарантированно модульна.


ре

Если нет, есть ли какой-нибудь предпочтительный способ решить проблему?

Используйте простой цикл, повторяющийся sizeof(unsigned) раз.

Код, о котором идет речь, похоже, был извлечен из такого цикла, так как постинкремент в *buf++ = i; совершенно бессмысленно (это последнее использование buf).

Да, присваивания вне диапазона типам без знака корректируют значение по модулю на единицу больше максимального значения, представляемого в типе. В этом случае мод UCHAR_MAX+1,

Исправление не требуется. Некоторые люди любят писать *buf++ = i % 0x100; или эквивалент, чтобы прояснить, что это было намеренное сужение.

Другие вопросы по тегам