стандарты — сужение конверсии в переполнении стека

В Руководство Биджа по сетевому программированию, есть функция, предназначенная для обеспечения переносимого способа сериализации 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 ++ = я & 0xFFFFU;

1

Решение

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

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

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

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

В итоге код не является переносимым.


ре

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

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

Единственная гарантия, что это по крайней мере 8 бит

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


ре

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

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

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

3

Другие решения

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

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

1

По вопросам рекламы [email protected]