意义
大端小端转化对嵌入式系统有意义,因为不同的处理器或者通信协议可能采用不同的字节序来存储或者传输数据。字节序是指一个多字节数据在内存中的存放顺序,它有两种主要的形式:
大端:最高有效位(MSB)存放在最低的内存地址,最低有效位(LSB)存放在最高的内存地址。
小端:最低有效位(LSB)存放在最低的内存地址,最高有效位(MSB)存放在最高的内存地址。
例如,一个32位的整数0x12345678,在大端系统中,它的内存布局是:
而在小端系统中,它的内存布局是:
如果一个嵌入式系统需要和不同字节序的设备或者网络进行交互,就需要进行字节序的转换,否则会导致数据错误或者通信失败。例如,TCP/IP协议族中的所有层都采用大端字节序来表示数据包头中的16位或32位的值,如IP地址、包长、校验和等。如果一个嵌入式系统使用小端字节序的处理器,并且想要建立一个TCP连接,就需要将IP地址等信息从小端转换为大端再发送出去,否则对方无法正确解析。
题目
输入一个数字n,假设它是以小端模式保存在机器的,请将其转换为大端方式保存时的值。
示例
输入:1
返回值:16777216
解答
1.char指针,按字节替换
/*
* @param n int整型
* @return int整型
*/
int convert(int n ) {
// write code here
int tmp = 0x00000000; //开辟新的int空间用于接收转化结果
unsigned char *p = &tmp, *q = &n;
p[0] = q[3];
p[1] = q[2];
p[2] = q[1];
p[3] = q[0];
return tmp;
}
2.利用union联合体共用内存空间特性,使用char数组来改变
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @return int整型
*/
typedef union {
int i;
unsigned char c[4]
} inc_u;
int convert(int n ) {
// write code here
inc_u x; //这里也可以用新开辟空间进行置换
x.i = n;
//利用按位异或运算可叠加、可还原性
x.c[0] ^= x.c[3], x.c[3] ^= x.c[0], x.c[0] ^= x.c[3]; //首尾两字节对调
x.c[1] ^= x.c[2], x.c[2] ^= x.c[1], x.c[1] ^= x.c[2]; //中间两字节对调
return x.i;
/*
按位<<到正确位置,并用|拼装
return (x.c[0]<<24)|(x.c[1]<<16)|(x.c[2]<<8)|x.c[3];
*/
}
3. 使用按位与运算保留以获取每个字节,然后按位左移到正确位置并拼接
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @return int整型
*/
int convert(int n ) {
// write code here
return (((n & 0xff000000)>>24) |
((n & 0x00ff0000)>>8 ) |
((n & 0x0000ff00)<<8 ) |
((n & 0x000000ff)<<24); //按位与时,遇0清零,遇1保留
);
}
4. 使用预定义好的宏函数
- 本条方法参考 https://www.codeproject.com/Articles/4804/Basic-concepts-on-Endianness
文中提到网络上常用的套接字接口(socket API)指定了一种称为网络字节顺序的标准字节顺序,这个顺序其实就是大端模式;而当时,同时代的 x86 系列主机反而是小端模式。所以就促使产生了如:
所以我们这里使用 32 bit 小转大的 htonl() 宏函数来解决这个问题。
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @return int整型
*/
int convert(int n ) {
// write code here
return htonl(n);
);
}
评论 (0)