数据大小端64位字节相互转换

在linux内核中有htonll()这个函数来进行网络大小端字节转换的功能,但是在Libc中没提供此函数,所以必须自己利用已用的函数进行封装。

大小端与数据存放顺序

C语言中,大于一个字节的数据类型在内存中表示时,不同CPU有不同的存放顺序,分为大端序和小端序。大端序即高字节存放在低地址,小端序相反。

  • 例: int x = 0x12345678, &x == 0x100,其大小端表示如下:
    数据大小端64位字节相互转换_第1张图片

字节序转换

通常在网络间传输数据时,因为是在不同机器上进行交互,所以需要先将数据转换成网络字节序,再发往对端。网络字节序是TCP/IP中定义的数据格式,与具体CPU、OS无关,采用大端表示。

常用的转换函数有:
#include

uint16_t htons(uint16_t hostshort); /* host to network short */

uint32_t htonl(uint32_t hostlong); /* host to networklong */

uint16_tntohs(uint16_tnetshort); /*network to host short */

uint32_t ntohs(uint32_t netlong); /*networkto host short */

现在如果需要将64位的long long类型数据从本机(小端)转换为网络字节序,就没有现成的API可用了。可以通过下面两种方法进行转换:

  1. 使用移位
unsigned long long u64_host, u64_net;
unsigned int  u32_host_h, u32_host_l;
u32_host_l = u64_host & 0xffffffff;
u32_host_h = (u64_host >> 32) & 0xffffffff;
 
u64_net = htonl(u32_host_l);
u64_net = ( u64_net << 32 ) | htonl(u32_host_h);
 
printf("htonll : %016llx\n", u64_net);

test >>>

in: 0x0102030405060708

out: 0x0807060504030201

  1. 使用联合体

根据联合体的特性:联合体中所有成员引用的是内存中相同的位置,其长度为最长成员的长度

typedef struct {
	unsigned int u32_h;
	unsigned int u32_l;
}Int64_t;
 
typedef union {
	unsigned long long u64;
	Int64_t st64;
}Convert64_t;
 
unsigned long long u64_host, u64_net;
Convert64_t box_in, box_out;
 
box_in.u64 = u64_host;
box_out.st64.u32_h = htonl(box_in.st64.u32_l);
box_out.st64.u32_l = htonl(box_in.st64.u32_h);
u64_net = box_out.u64;
 
printf("htonll : %016llx\n", u64_net);

你可能感兴趣的:(c)