1

Beej 的网络编程指南中,有一个函数旨在提供一种可移植的方式来序列化 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;

4

2 回答 2

3

该代码假定为 8 位字节,并且不可移植。

例如,一些德州仪器数字信号处理器具有 16 位字节。

每个字节的位数由CHAR_BITfrom给出<limits.h>

此外,代码假定它unsigned是 16 位,这是不可移植的。

总之,代码不可移植。


回覆

C++ 标准是否保证在这样的转换中,unsigned int 总是被截断,并且它的最低有效 8 位保留在 unsigned char 中?

不,因为 C++ 标准不保证每个字节的位数是 8。

唯一的保证是它至少是8 位。

然而,无符号算术是保证模块化的。


回覆

” 如果没有,有没有首选的方法来解决这个问题?

使用一个简单的循环,迭代sizeof(unsigned)次数。

有问题的代码似乎是从这样的循环中提炼出来的,因为 in 的后增量*buf++ = i;完全没有意义(这是 的最后一次使用buf)。

于 2014-09-07T12:34:34.747 回答
1

是的,对无符号类型的超出范围的赋值会调整值以比该类型中可表示的最大值大一为模。在这种情况下, mod UCHAR_MAX+1

无需修复。有些人喜欢写*buf++ = i % 0x100;或等效,以明确表示这是故意缩小范围。

于 2014-09-07T12:28:26.883 回答