结构体

结构体对齐

摘自原则:

  • 结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存中时,它都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始(以结构体变量首地址为0计算)。
  • 在经过第一原则分析后,检查计算出的存储单元是否为所有元素中最宽的元素的长度的整数倍,是,则结束;若不是,则补齐为它的整数倍。

我这边补在赘述结构体的对齐原则,上面一篇文章详细讲了,可供大家参考。
新建一个结构体

typedef struct test_struct
{uint8_t A;uint16_t B;uint32_t C;
}test_t;test_t test;
uint16_t size  = 0;//查看大小
uint8_t *A_addr;
uint16_t *B_addr;
uint32_t *C_addr;
woid main()
{test.A = 1;test.B = 2;test.C = 3;size = sizeof(test);A_addr = &test.A;B_addr = &test.B;C_addr = &test.C;while(1){}
}

首先是结构体的大小为:8

各个元素的地址

在内存中是这样的:
XX表示未被初始化的内存,虽然也是00,但是我们为了区分所以用XX表示

压缩结构体的方法

__packed

定义

__packed在 "cmsis_armcc.h"文件中定义:

#ifndef   __PACKED#define __PACKED                               __attribute__((packed))

作用

packed属性的主要目的是让编译器更紧凑地使用内存。当它用于变量时,告诉编译器该变量应该有尽可能小的对齐,也就是1字节对齐。当它用于结构体时 ,相当于给该结构体的每个成员加上了packed属性,这时该结构体将占用尽可能少的内存。

typedef __packed struct test_struct
{uint8_t A;uint16_t B;uint32_t C;
}test_t;	

使用__packed之后结果:

从上图中可以发现结构体成员地址向前移动了一个,其内存模型如下:

#pragma

语法

  • #pragma pack (n) 作用:C编译器将按照n个字节对齐。

  • #pragma pack () 作用:取消自定义字节对齐方式。

  • #pragma pack (push,1) 作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为一个字节对齐

  • #pragma pack(pop) 作用:恢复对齐状态

结果

结果与__packed一致都是按字节对齐的。

#pragma pack(1)
typedef struct test_struct 
{uint8_t A;uint16_t B;uint32_t C;
}test_t;
#pragma pack ()