#pragma用于指示编译器(预处理阶段)完成一些特定的动作,它有以下特性
1、#pragma在不同的编译器间是不可移植的,预处理器会忽略它不认识的#pragma指令
2、不同的编译器可能会以不同的方式解释同一条#pragma指令
一般用法:#pragma 参数
常见的参数有message once pack
message用法:用于在预处理时提供打印版本信息,大多数编译器都有相同的实现
#if define(CPLUSPLUS17)
#pragma message("C++ version is 17")
#define VERSION "C++17"
#endif
once用法:用于保证头文件只被编译一次,编译器相关的,不一定支持
eg:有时候编译会报“XXX redefination”( 这可能是因为当前文件把所有包含的头文件展开时,因为互相包含的原因,可能会把某一个头文件展开多次,如果恰好这个头文件中定义了一个全局变量,这个全局变量又在当前文件中有使用,这时就会报这个错 )
pack用法:常用于指定内存对齐
什么是内存对齐?
不同的数据在内存中按照一定规则排列,而不是顺序的一个接一个排列,这种规则就是内存对齐
为什么需要内存对齐?
1、CPU对内存的读取不是连续的,而是分块读取的,块的大小只能是1、2、4、8、16.....字节
2、当读取的数据未对齐,则需要两次总线周期来访问内存,因此性能会下降
3、某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则会产生硬件异常
struct占用内存大小:
1、第一个成员起始0偏移处
2、每个成员必须按照其类型大小和pack参数中较小的一个进行对齐(对齐参数)
a. 偏移地址必须能被对齐参数整除
b. 结构体成员的大小取其内部长度最大的数据成员作为其大小
3、结构体总长度必须为所有对齐参数的整数倍
4、编译器默认按4字节对齐(gcc目前最多支持4字节对齐)
//例程1
#include<stdio.h>
struct Test1
{
/* 12 */
char c1;
short s;
char c2;
int i;
};
struct Test2
{
/* 8 */
char c1;
char c2;
short s;
int i;
};
int main()
{
printf("sizeof(struct Test1) = %d sizeof(struct Test2) = %d",sizeof(struct Test1),sizeof(struct Test2));
return 0;
}
/*运行结果 sizeof(struct Test1) = 12 sizeof(struct Test2) = 8*/
//例程2
#include<stdio.h>
#pragma pack(1)
struct Test1
{
/* 8 */
char c1;
short s;
char c2;
int i;
};
#pragma pack(1)
struct Test2
{
/* 8 */
char c1;
char c2;
short s;
int i;
};
int main()
{
printf("sizeof(struct Test1) = %d sizeof(struct Test2) = %d",sizeof(struct Test1),sizeof(struct Test2));
return 0;
}
/*运行结果 /*运行结果 sizeof(struct Test1) = 8 sizeof(struct Test2) = 8*/
//例程3
#include<stdio.h>
#pragma pack(4)
struct Test1
{
/* 12 */ //对齐参数 偏移地址 大小
char c1; //1 0 1
short s; //2 2 2
char c2; //1 4 1
int i; //4 8 4
};
#pragma pack(4)
struct Test2
{
/* 8 */ //对齐参数 偏移地址 大小
char c1; //1 0 1
char c2; //1 1 1
short s; //2 2 2
int i; //4 4 4
};
int main()
{
printf("sizeof(struct Test1) = %d sizeof(struct Test2) = %d",sizeof(struct Test1),sizeof(struct Test2));
return 0;
}
/*运行结果 sizeof(struct Test1) = 12 sizeof(struct Test2) = 8*/
参考:狄泰软件唐老师