C语言中无符号64位数字的字节顺序转换问题
我正在玩little endian/big endian转换,发现有些东西有点混乱,但也很有趣 在第一个示例中,使用位移位转换C语言中无符号64位数字的字节顺序转换问题,c,gcc,uint32,C,Gcc,Uint32,我正在玩little endian/big endian转换,发现有些东西有点混乱,但也很有趣 在第一个示例中,使用位移位转换uint32\u t类型的字节顺序没有问题。它基本上将一个uint32\u t整数转换为uint8\u t数组,并尝试访问每个字节和位移位 示例#1: 为了使其工作,我必须将每个字节提取到一个uint64_t中,这样我就可以在没有任何错误的情况下进行位移位,如下面的示例3所示 示例#3: uint64\u t htonl2(uint64\u t x) { uint64字节
uint32\u t
类型的字节顺序没有问题。它基本上将一个uint32\u t
整数转换为uint8\u t
数组,并尝试访问每个字节和位移位
示例#1:
为了使其工作,我必须将每个字节提取到一个uint64_t
中,这样我就可以在没有任何错误的情况下进行位移位,如下面的示例3所示
示例#3:
uint64\u t htonl2(uint64\u t x)
{
uint64字节1=x&0xff00000000000000;
uint64字节2=x&0x00ff000000000000;
uint64字节3=x&0x0000ff0000000000;
uint64字节4=x&0x000000ff00000000;
uint64字节5=x&0x00000000ff000000;
uint64字节6=x&0x0000000000ff0000;
uint64字节=x&0x000000000000ff00;
uint64字节8=x&0x00000000000000ff;
返回(uint64_t)(字节1>>56;字节2>>40;字节3>>24;字节4>>8|
当在表达式中使用时,类型小于int
的字节5值将提升为int
。假设平台上的int
为32位,则在大多数情况下,在转换32位值时,此操作都有效。如果将1位移到符号位,则此操作不起作用
在64位的情况下,这意味着您正试图将一个值移位超过其未定义行为的位长度
在这两种情况下,您都需要将每个字节强制转换为uint64\t
,以允许移位正常工作。s[0]
表达式有一个8位宽的整数类型,当移位运算符对其进行操作时,该类型被提升为32位无符号整数–因此s[0]uint8\u t
将被提升为int
。它将是有符号的,而不是无符号的,并且它将是int
的任何宽度,现在通常是32位,但C标准允许是16位或更多。这将不起“OK”作用因为,如果uint8\u t
的高位打开且int
为32位,则24位的移位将溢出int
中可表示的值的范围,并且行为不由C标准定义。
uint32_t htonl(uint32_t x)
{
uint8_t *s = (uint8_t*)&x;
return (uint32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
}
uint64_t htonl(uint64_t x)
{
uint8_t *s = (uint8_t*)&x;
return (uint64_t)(s[0] << 56 ......);
}
uint64_t htonll2(uint64_t x)
{
uint64_t byte1 = x & 0xff00000000000000;
uint64_t byte2 = x & 0x00ff000000000000;
uint64_t byte3 = x & 0x0000ff0000000000;
uint64_t byte4 = x & 0x000000ff00000000;
uint64_t byte5 = x & 0x00000000ff000000;
uint64_t byte6 = x & 0x0000000000ff0000;
uint64_t byte7 = x & 0x000000000000ff00;
uint64_t byte8 = x & 0x00000000000000ff;
return (uint64_t)(byte1 >> 56 | byte2 >> 40 | byte3 >> 24 | byte4 >> 8 |
byte5 << 8 | byte6 << 24 | byte7 << 40 | byte8 << 56);
}