基础笔记3 —— 关于大小端数据存储方式的转换及测试说明

文章目录

  • 说明
  • 1.大小端概念
  • 2.各自的优势
  • 3.现阶段大小端模式的使用情况[^1]
  • 4.测试所用设备的数据存储方式
    • 4.1 使用union测试机器大小端
    • 4.2 使用指针测试
  • 5.大小端的转换

说明

为什么会关心大小端问题 ?

在控制系统中,由于CPU架构以及编译器等因素决定了数据的存储方式,不同的存储方式,其数据的发送/解读方式需要使用响应的方法。

因此,在数据传输时,我们有必要弄清楚两台或多台设备的存储方式是大端还是小端。尤其是在两台存储方式不同的设备之间实现通信,必须要搞明白这件事情,否则可能会导致数据解读不正确的问题。

大小端的起源不在进行赘述,请参考维基百科等文献。

1.大小端概念

  • 大端(Big-Endian): 低地址存放高位

  • 小端(Little-Endian): 低地址存放低位

举个栗子,对于0x12345678这个数,存放在地址0x4000中,大小端的存储方式区别如下表:

内存地址 小端模式存放内容 大端模式存放内容
0x4000 0x78 0x12
0x4001 0x56 0x34
0x4002 0x34 0x56
0x4003 0x12 0x78

再来个更直观的叙述方式:

对于大端模式:

  • 低地址---------->高地址
    0X12|0X34|0X56|0X78|

对于小端模式:

  • 低地址---------->高地址
    0X78|0X56|0X34|0X12|

2.各自的优势

  • 大端存储:顺序存储,符合人的思维,符号位的判定固定为第一个字节,容易判断正负;

  • 小端存储:强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。

3.现阶段大小端模式的使用情况1

  • 目前Intel的80x86系列芯片是唯一还在坚持使用小端的芯片;
  • ARM芯片默认采用小端,但可以切换为大端;
  • MIPS等芯片要么采用全部大端的方式储存,要么提供选项支持大端——可以在大小端之间切换;

另外,对于大小端的处理也和编译器的实现有关:

  • 在C语言中,默认是小端(但在一些对于单片机的实现中却是基于大端,比如Keil 51C);
  • Java是平台无关的,默认是大端。

此外,

  • 在网络上传输数据普遍采用的都是大端。

4.测试所用设备的数据存储方式

对于这个问题,百度百科也给出了一些测试程序1

测试方法由多种:

4.1 使用union测试机器大小端

#include 

int check_sys()
{
	union UN
	{
		char c;
		int i;
	}un;
	un.i = 1;
	if (un.c == 1)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("Is big endian\n");
	}
	else
	{
		printf("Is little endian\n");
	}
	return 0;
}

4.2 使用指针测试

#include 
int check_sys()
{
 int i = 1;
 int *p = &i;
 char *q = (char *)p;
 if (*q == 1)
 {
  return 0;
 }
 else
 {
  return 1;
 }
}
int main()
{
 int ret = check_sys();
 if (ret == 1)
 {
  printf("Is big endian\n");
 }
 else
 {
  printf("Is little endian\n");
 }
 return 0;
}

5.大小端的转换

思路1:直接交换字节
思路2:先与再移位,得到各地址的数据,最后按相应的顺序排列

( a&0x000000ff<< 24 )   |   ( ( a&0x0000ff00 ) << 8 )   |   ( ( a&0x00ff0000 ) >> 8 )   |   ( ( a&0xff000000 )  >> 24 )

具体代码参见其他博文。


  1. https://baike.baidu.com/item/%E5%A4%A7%E5%B0%8F%E7%AB%AF%E6%A8%A1%E5%BC%8F/6750542?fr=aladdin ↩︎ ↩︎

你可能感兴趣的:(▶,Linux/嵌入式,▼,程序人生,#,▶,C/C++)