结构体对齐#pragma pack(n),#pragma pack(push)和#pragma pack(pop)

前言

我们都知道结构体内存对齐字节可以通过#pragma pack(n)的方式指定。
但是,有时候我想这个结构体用1字节对齐,下一个结构体用4字节对齐,那怎么办呢?

测试

#include <stdio.h>

#pragma pack(1)
struct AA{
	double a;
	int b;
    short c;
    char d;
    char e;
    char f;
}
#pragma pack() 
struct BB{
	double a;
	int b;
    short c;
    char d;
    char e;
    char f;
}
int main(void) { 
	printf("%u\n%u\n",sizeof(struct AA),sizeof(struct BB));
	return 0;
}

结果是:结果1
这说明了,在强制1字节对齐之后,我加上#pragma pack() ,能够让程序恢复默认对齐(这里是8字节)状态。
2.

#include <stdio.h>
//#pragma pack(push)
#pragma pack(1)
struct AA{
	double a;
	int b;
    short c;
    char d;
    char e;
    char f;
}
#pragma pack(pop) 
struct BB{
	double a;
	int b;
    short c;
    char d;
    char e;
    char f;
}
int main(void) { 
	printf("%u\n%u\n",sizeof(struct AA),sizeof(struct BB));
	return 0;
}

结果是:
结果
那如果加上#pragmatic pack(push)后呢
结果

总结

#pragma pack(push):英文单词push是“压入”的意思。编译器编译到此处时将保存对齐状态(保存的是push指令之前的对齐状态)。

#pragma pack(pop):英文单词pop是”弹出“的意思。编译器编译到此处时将恢复push指令前保存的对齐状态(请在使用该预处理命令之前使用#pragma pack(push))。

push和pop是一对应该同时出现的名词,只有pop没有push不起作用,只有push没有pop可以保持之前对齐状态(但是这样就没有使用push的必要了)。

这样就可以知道,当我们想要一个结构体按照4字节对齐时,可以使用#pragma pack(4)

struct{
}

#pragma pack() ;
也可以使用:
#pragma pack(push)
#pragma pack(4)

struct{
}

#pragma pack(pop)

这样在push和pop之间的结构体就可以按照pack指定的字节(这里是4字节对齐方式),而pop之后的结构体按照#pragma pack(push) 前对齐方式。
也可以这样:
#pragma pack(push,4)

struct{
}

#pragma pack(pop)

这是给编译器用的参数设置,有关结构体字节对齐方式的设置大概是指把原来对齐方式设置压栈,并设新的设置为4

例子

#include <stdio.h>
//#pragma pack(push)
#pragma pack(push,2)
struct AA{
	double a;
	int b;
    short c;
    char d;
    char e;
    char f;
};
#pragma pack(1)
struct BB{
	double a;
	int b;
    short c;
    char d;
    char e;
    char f;
};
#pragma pack(pop)
struct CC{
	double a;
	int b;
    short c;
    char d;
    char e;
    char f;
};
int main(void) { 
	printf("%u\n%u\n%u\n",
		sizeof(struct AA), sizeof(struct BB), sizeof(struct CC));
	return 0;
}

结果是:结果
分析:第一个结构体AA是按照2字节对齐,第二个结构体是按照1字节对齐的,最后一个则恢复为8字节对齐。

你可能感兴趣的:(02,Keil/c/c++,嵌入式)