也谈大小端
来源:互联网 发布:精子优化处理检查 必要 编辑:程序博客网 时间:2024/06/05 05:10
大小端问题是一个很简单的概念,但在实际使用中却是一个所必须考虑的非常重要的细节。虽然简单却也曾经困扰过我很多次,今天正好有空整理出来做个笔记。
字节序的大小端通常指的是在一个字内(32位或者64位)各字节在内存中的存放顺序。注意这里仅是一个字内Byte的顺序,各个字之间的顺序不受大小端的影响。另外还要注意想一个int数据进行左右移位是跟大小端没关系的,因为编译器已经屏蔽了这层差异,不要混淆。另外值得注意的一点是,字节内的bit位也是有大小端区分的,这个在通信协议中需要重点关注。
1)在Big Endian的情况下,"排在前面的是高位"
a. 对于顺序的两个字节来说,第一个字节是高位(排在前面),第二个字节是低位(排在后面)。
b. 对于字节内部的位来说,
-------most significant bits排在前面,是高位,
-------least significant bits排在后面,是低位。
2)在Little Endian的情况下,"排在前面的是低位"
a. 对于顺序的两个字节来说,第一个字节是低位(排在前面),第二个字节是高位(排在后面)。
b. 对于字节内部的位来说,
-------least significant bits排在前面,是低位,
-------most significant bits排在后面,是高位。
大端中一个字内的高有效位在低地址,低有效位在高地址;小端正好相反。
下面以0x12345678,在大端情况下在内存的存放为:
内存地址 : 0x10000000 0x10000001 0x10000002 0x10000003
大端: 0x12 0x34 0x56 0x78
小端: 0x78 0x56 0x34 0x12
可见小端正好和我们日常的书写顺序相反,助记口诀----小反(三国杀中的反贼角色)。
在实际编码中,我们经常需要将一个buffer数组转换成大小端相关的uint32。来看一个例子:
在实际使用中多是,主机字节序与网络字节序(或者寄存器读出来的数据)之间的转换,转换类型有三种:
1、U32或者U16字节序转换;
2、UCHAR数组和UINT32之间的相互转换;
3、结构体中位域的大小端(参见我的另外一篇博客--位域与大小端);
下面是几个例子:
1.1 判 断大小端代码
judge_endian()
{
uint a= 1;
if (*((char *)&a))
printf(“BIGEndian\r\n”);
}
1.1.2 UINT字节序转换
htonl的意思是 host to network long
#if defined(LE_HOST)
#define htonl(_l) _ swap32(_l)
#define htons(_s) _ wap16(_s)
#define ntohl(_l) _ swap32(_l)
#define ntohs(_s) _ swap16(_s)
#else
#define htonl(_l) (_l)
#define htons(_s) (_s)
#define ntohl(_l) (_l)
#define ntohs(_s) (_s)
#endif
unsigned int _swap32(unsigned int i)
{
i = (i << 16) | (i >> 16);
return (i & 0xff00ffff) >> 8 | (i & 0xffff00ff) <<8;
}
unsigned short _swap16(unsigned short i)
{
return i << 8 | i >> 8;
}
1.1.3 UINT与char数组字节序转换
字-->char数组
chipc_spi_read(uint8 * buf, int len)
{
/* chipc_spi_fifo_readword读取寄存器,返回uint类型*/
/*将获取到的value值根据字节序转换到char数组中去*/
#if defined(BE_HOST)
value = 0;
for (idx =0 ; idx < len ; idx++) {
m = idx% 4;
if (m== 0) {
value = chipc_spi_fifo_readword();
}
*buf++= (uint8)(value >> ((3-m)*8));
}
#else
value = 0;
for (idx =0 ; idx < len ; idx++) {
m = idx% 4;
if (m== 0) {
value = chipc_spi_fifo_ readword ();
}
*buf++= (uint8)(value >> (m*8));
}
#endif
}
char数组-->字
chipc_spi_write_fifo(uint8 *data, int len)
{
/*将char数组的值转换成uint,然后通过chipc_spi_fifo_writeword函数写到寄存器里去*/
#if defined(BE_HOST)
value = 0;
for (idx =0 ; idx < len ; idx++) {
m = idx% 4;
value|= (*data << ((3-m)*8));
data++;
if ((m== 3) || (idx == (len - 1))) {
chipc_spi_fifo_writeword(value);
value = 0;
}
}
#else
value = 0;
for (idx =0 ; idx < len ; idx++) {
m = idx% 4;
value|= (*data << (m*8));
data++;
if ((m== 3) || (idx == (len - 1))) {
chipc_spi_fifo_writeword(value);
value = 0;
}
}
#endif
}
- 也谈大小端
- 也谈大端小端
- 让对话框也可以通过拖放来改变大小
- delphi里窗体改变大小怎么让里边的TreeView,GroupBox也随着改变大小
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- c#当窗体大小改变时,窗体中的控件大小也随之改变
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- C#当窗体大小改变时,窗体中的控件大小也随之改变
- c#实现窗体大小改变时,控件大小也跟着改变,实现窗体拉伸重绘
- 大小端
- 大小端
- 大小端
- 大小端
- 桌面GIS平台效率提升的一点小经验
- adb 联系手机异常解决方法
- 百度地图API之根据经纬度查询地址信息(Android)
- 又拍网架构中的分库设计(转)
- oscache的使用
- 也谈大小端
- 百度地图API之MyLocationOverlay的使用(Android)
- c++ 进程守护之打不死的小强
- Java基础-关于session的详细解释
- Vitamio中文API文档(1)—— VideoView
- UITabBarController使用详解
- 常用命令
- SqlCmd命令行工具运用
- 模板方法设计模式--学习笔记