一文讲清楚大小端模式,字节对齐与左右对齐

目录

大小端

一、什么是大小端模式

二、为什么会有大小端之分

三、怎样判断大小端

1、通过强制类型转换截断

2、利用联合体共享内存的特性,截取低地址部分

字节对齐

1、什么是内存对齐?

2、为什么要内存对齐?

3、内存对齐规则?

4、C++如何进行内存对齐?

ADC读取左对齐与右对齐

1.右对齐数据读取问题

2.左对齐数据读取问题

大小端

一、什么是大小端模式

一个32位的2进制在内存中存储时有两种发布方式:

高字节 对应 高地址 --------------> 小端模式

高字节 对应 低地址 --------------> 大端模式

示意图如下:

二、为什么会有大小端之分

1. 一开始是由于不同架构的CPU处理多个字节数据的顺序不一样,比如x86的是小段模式,KEIL C51是大端模式。但是后来互联网流行,TCP/IP协议规定为大端模式,为了跨平台通信,还专门出了网络字节序和主机字节序之间的转换接口(ntohs、htons、ntohl、htonl)

2. 大小端模式各有优势:小端模式强制转换类型时不需要调整字节内容,直接截取低字节即可;大端模式由于符号位为第一个字节,很方便判断正负。

三、怎样判断大小端

基本思想室根据数据截断来判断是大端还是小端

1、通过强制类型转换截断

BOOL IsBigEndian()

{

short a = 0x1234;

char b = *(char*)&a;

if(0x12 == b)

{

return TRUE;

}

return FALSE;

}

2、利用联合体共享内存的特性,截取低地址部分

BOOL IsBigEndian()

{

union NUM

{

short a;

char b;

}num;

num.a = 0x1234;

if(0x12 == num.b)

{

return TRUE;

}

return FALSE;

}

字节对齐

1、什么是内存对齐?

理论上计算机对于任何变量的访问都可以从任意位置开始,然而实际上系统会对这些变量的存放地址有限制,通常将变量首地址设为某个数N的倍数,这就是内存对齐。

2、为什么要内存对齐?

硬件平台限制,内存以字节为单位,不同硬件平台不一定支持任何内存地址的存取,一般可能以双字节、4字节等为单位存取内存,为了保证处理器正确存取数据,需要进行内存对齐。提高CPU内存访问速度,一般处理器的内存存取粒度都是N的整数倍,假如访问N大小的数据,没有进行内存对齐,有可能就需要两次访问才可以读取出数据,而进行内存对齐可以一次性把数据全部读取出来,提高效率。

3、内存对齐规则?

数据成员对齐规则:struct或者union的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员都按照#pragma pack数值和这个数据成员自身大小中更小的那个进行对齐。整体对齐规则:struct或者union的首地址按照内部最大数据成员的大小和#pragma pack数值较小的那个N进行对齐,并且结构体的总大小为N的整数倍,如有必要编译器也会在最后一个成员后面填充一些字节用于对齐。

4、C++如何进行内存对齐?

class A

{

int a;

char d;

};

// 创建给定类型对象大小满足对齐要求的未初始化内存块,在一个内存对齐的缓冲区上创建对象

// C++11后可以这样操作

void align_cpp11_after()

{

static std::aligned_storage

alignof(A)>::type data;

A *attr = new (&data) A;

}

// C++11之前

void align_cpp11_before()

{

static char data[sizeof(void *) + sizeof(A)];

const uintptr_t kAlign = sizeof(void *) - 1;

char *align_ptr =

reinterpret_cast(reinterpret_cast(data + kAlign) & ~kAlign);

A *attr = new (align_ptr) A;

}

ADC读取左对齐与右对齐

1.右对齐数据读取问题

其转换结果可以读取的语句为: resualt=int(ADCH)*256+ADCL; 右对齐的时候,10位ADC的结果表示方式为ADCH:ADCL,ADCH是10bit结果的高2位,ADCL是10bit结果的低8位,如果要将ADC的结果存储到一个int型的变量中,那就需要先将ADCH的结果左移8位,再和ADCL的相加,其原理如下图所示:

左移8位等价于乘以256. 也可以将ADC转化为以256为权的数值表示,即: resualt = int(ADCH)*256^1+ADCL*256^0; 这样就可以清楚地理解这个数字的含义了。

2.左对齐数据读取问题

同理,左对齐如下表示:

Back to top: