内存对齐/大小端

忘了的时候就回来看看这篇文章

大小端的定义

大端(BE):内存的起始地址存放高位的数据
小端(LE):内存的起始地址存放地位的数据
0x12345678 12在高位 78在低位
大端存储为(左至右为内存低地址->高地址): 12 34 56 78
小端存储为(左至右为内存低地址->高地址):78 56 34 12

为什么要有大小端

TCP等协议规定传输时数据遵循大端原则
大多数系统内存中的数据遵循小端原则
因为一开始没有统一的规范,各系统定义不同,造成了后面这种两端开花的局面

如何快速做大小端转换

socket常用代码

#include<arpa/inet.h>

uint64_t i = 0x00010001;
//host to net test
cout << i << " " << htonl(i) << endl;//对应的ntohl

输出结果

65537 16777472

分别对应 0x00010001 和 0x01000100

怎么判断系统是大端还是小端

强制类型转换测试

//le be test
if (*(char*)&i == 0x00)
{
  cout << "big endian" << endl;
}
else
{
  cout << "small endian" << endl;
}

输出结果

small endian

说明我的linux服务器是小端存储

什么是内存对齐

例如C++中常见struct结构体占用的内存并不是简单按照元素占用空间累加
计算占用空间时遵循3原则
1.每一个元素的起始地址必须被自己的大小整除
2.结构体总大小必须被最大元素的大小整除
3.如果设置了#parma pack(n), 第2点改为结构体总大小能被(最大元素和n的较小者)整除 n默认为4

struct memOffset
{
  uint16_t a;
  uint32_t b;
  uint64_t c;
};
/*
 00000000|00000000|0000000000000000
 a        b        c
*/
//memoffset test
memOffset j;
cout << "sizeof j is " << sizeof(j) << endl;

输出结果

size of j is 16

a占2字节,起始位置为0
b占4字节,起始位置为4(为满足条件1, a后面填充两字节)
c占8字节,起始位置为8

补充一点,如果结构体中包含结构体,则
1.子结构体内的元素起始位置为子结构体内最大元素的倍数
2.子结构体的总大小(如果是父结构体内所有元素中最大的)不能当作父结构体内的最大成员来判断,比如

struct A  
{  
      uint16_t i;  //start with 0, size is 2
      struct   
      {  
           uint8_t j;  //start with 4, size is 1
           uint32_t k;  //start with 8, size is 4
      } l;   //all size is 8
      uint32_t m;  //start with 12, size is 4
      uint8_t n;//start with 16, size is 1
};  //all size is 20, not 24

输出结果

sizeof struct struct is 20

为什么要做内存对齐

操作系统中读取内存以页为单位,如果不做内存对齐,即读取的内容地址不是按照页大小的整数倍开始
很可能导致原本一页可以读完的数据被划分到多页上,多次读取和拼接操作降低了系统性能。

内存对齐结合大小端

把之前的i强制转换成结构体j

memset(&j, 0, sizeof(j));
memcpy(&j, &i, sizeof(i));
//i is 01 00 01 00
cout << j.a << " " << j.b << " " << j.c << endl;

输出结果

1 0 0

i为 0x00010001,补充到64位为0x0000000000010001
系统按小端存储,i内存中实际内容为 01 00 01 00 00 00 00 00
根据结构体j的对其规则,及小端存储原则
a占2字节, 内容为01 00
对齐占2字节, 内容为 01 00
b占4字节, 内容为 00 00 00 00
c占8字节,超过了i的长度,全为0
最后小端存储转换为实际值
a = 0x0001
b = 0x00000000
c = 0x0000000000000000
结果是1 0 0

发布者

VC-Robot

游戏爱好者,动漫迷,C++修炼中,编程菜鸟,随性

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据