Сужающее преобразование в 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;
или эквивалент, чтобы прояснить, что это было намеренное сужение.