long long 类型的网络字节顺序转换
时间:2006-07-04 来源:redfoxlinux
做过socket的都知道网络字节转换的事情,网络中传输的数据有的和本地字节存储顺序一致,而有的则截然不同,为了数据的一致性,就要把本地的数据转换成网络上使用的格式,然后发送出去,接收的时候也是一样的,经过转换然后才去使用这些数据,基本的库函数中提供了这样的可以进行字节转换的函数,如和htons( ) htonl( ) ntohs( ) ntohl( ),这里n表示network,h表示host,htons( ) htonl( )用于本地字节向网络字节转换的场合,s表示short,即对2字节操作,l表示long即对4字节操作。同样ntohs( )ntohl( )用于网络字节向本地格式转换的场合。随着c99标准的推行,我们伟大的c中增加了新的类型long long int ,unsigned long long int,都是64位的,怎么办?不转肯定是不行,就得自己想办法把它转了。当然有很多方法,我这里想使用一种递归的解决方法,证明咱也看过“艺术”。
首先考虑网络字节转换的结果与原来有什么不同(我这里举的例子都是使用little endian的IA-32架构上面的Linux),如 int a = 0x12345678,b = htnl(a),那么就应该是0x78563412。如果是 short c = 0x1234,short d = 0x5678,e = htons(c),f = htons(d),这样e=0x3412,f=0x7856,如果能把e和f调换一下组合放在一起,不就是一个整型a(a=0x12345678)转换之后的值么。实验的代码如下:
#include <stdio.h>
struct ST{
short val1;
short val2;
};
union U{
int val;
struct ST st;
};
int main(void)
{
int a = 0;
union U u1, u2;
a = 0x12345678;
u1.val = a;
printf("u1.val is 0x%x\n", u1.val);
printf("val1 is 0x%x\n", u1.st.val1);
printf("val2 is 0x%x\n", u1.st.val2);
printf("after first convert is: 0x%x\n", htonl(u1.val));
u2.st.val2 = htons(u1.st.val1);
u2.st.val1 = htons(u1.st.val2);
printf("after second convert is: 0x%x\n", u2.val);
return 0;
}
输出结果:
u1.val is 0x12345678
val1 is 0x5678
val2 is 0x1234
after first convert is: 0x78563412
after second convert is: 0x78563412
按照这种想法我们实现long long int(64bit) 类型,把它分割成两个int(32bit) ,然后分别使用htonl(),分别转换,然后再从新组合数据。
代码如下:
#include <stdio.h>
struct ST{
int val1;
int val2;
};
union test {
long long int val;
struct ST st;
};
int main(void)
{
long long int a;
union test u1, u2;
a = 0x7654321087654321LL;
u1.val = a;
u2.st.val2 = htonl(u1.st.val1);
u2.st.val1 = htonl(u1.st.val2);
printf("val1 is 0x%x\n", u2.st.val1);
printf("val2 is 0x%x\n", u2.st.val2);
printf("u1.val is : 0x%llx\n", u1.val);
printf("after convert is : 0x%llx\n", u2.val);
return 0;
}
执行结果:
val1 is 0x10325476
val2 is 0x21436587
u1.val is : 0x7654321087654321
after convert is : 0x2143658710325476
另外注意long long int 最大值是0x7fffffffffffffff,即7后面15个f(2的63次方减1) unsigned long long int 最大值是0xffffffffffffffff,16个f(2的64次方减1)。程序中long long int 可以简写为 long long,但是记住这是简写,就像long是long int的简写。
想看数据在内存中如何存储的,就用gdb吧!使用gdb中 x命令,如 x /xb &a表示要察看存储在变量a中的前一个字节(byte)中的数据(16进制)。x /xw &a 就是要察看变量a中前4个字节(word)数据(16进制)。x /xg &a 察看a开始8个字节的数据。自己去看看吧。