在Beej's Guide to Network Programming中,有一个函数旨在提供一种序列化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
)会导致转换变窄
unsigned int
始终被截断,其最低有效8位保留在unsigned char
?如果没有,是否有任何解决问题的首选方法?是否足以将函数体更改为以下内容?
* buf ++ =(i>> 8)& 0xFFFFU; * buf ++ = i& 0xFFFFU;
答案 0 :(得分:3)
代码假定为8位字节,并且不可移植。
E.g。一些德州仪器的数字信号处理器具有16位字节。
每个字节的位数由CHAR_BIT
的{{1}}给出。
此外,代码假定<limits.h>
是16位,这是不可移植的。
总之,代码不可移植。
RE
“ C ++标准是否保证在这种转换中,unsigned int总是被截断,其最低有效8位保留在unsigned char中?
不,因为C ++标准不保证每个字节的位数是8。
唯一的保证是至少 8位。
无符号算术是保证模块化的。
RE
“如果没有,是否有任何解决问题的首选方法?
使用一个简单的循环,迭代unsigned
次。
有问题的代码似乎是从这样的循环中提炼出来的,因为sizeof(unsigned)
中的后增量完全没有意义(这是*buf++ = i;
的最后一次使用。)
答案 1 :(得分:1)
是的,对无符号类型的超出范围分配会调整模数值,使其大于类型中可表示的最大值。在这种情况下,mod UCHAR_MAX+1
。
无需修复。有些人喜欢写*buf++ = i % 0x100;
或等同,以明确这是故意缩小的。