关于之前对#pragma pack ()误解的纠正

如题

首先给出一段之前测试的代码

 

#include<stdio.h>
#pragma pack (4)
typedef struct a
{
	int b; //4
	char c; //1
	short d;//2
	float e;//4
	char f; //1
} st;

int main()
{
	st s;
	printf("%d\n",sizeof(s));
	printf("str   s:  %p\n",&s);
	printf("int   b:  %p\n",&(s.b));
	printf("char  c:  %p\n",&(s.c));
	printf("short d:  %p\n",&(s.d));
	printf("float e:  %p\n",&(s.e));
	printf("char  f:  %p\n",&(s.f));
	
	return 0;

}


原来理解为:为每个数据成员分配的内存大小都没4个字节,不足的补0,实际是一种误解。

实际结果为:

 

16
str   s:  0022FEE0
int   b:  0022FEE0
char  c:  0022FEE4
short d:  0022FEE6
float e:  0022FEE8
char  f:  0022FEEC


内存分配为 1111_10_11_1111_1000    16byte

 

改变程序代码为#pragma pack (8) :

 

#include<stdio.h>
#pragma pack (8)
typedef struct a
{
	int b; //4
	char c; //1
	short d;//2
	float e;//4
	char f; //1
} st;

int main()
{
	st s;
	printf("%d\n",sizeof(s));
	printf("str   s:  %p\n",&s);
	printf("int   b:  %p\n",&(s.b));
	printf("char  c:  %p\n",&(s.c));
	printf("short d:  %p\n",&(s.d));
	printf("float e:  %p\n",&(s.e));
	printf("char  f:  %p\n",&(s.f));
	
	return 0;

}

 

运行结果是一致的;

16
str   s:  0022FEE0
int   b:  0022FEE0
char  c:  0022FEE4
short d:  0022FEE6
float e:  0022FEE8
char  f:  0022FEEC



 

改变程序代码为#pragma pack (2) :

 

#include<stdio.h>
#pragma pack (2)
typedef struct a
{
	int b; //4
	char c; //1
	short d;//2
	float e;//4
	char f; //1
} st;

int main()
{
	st s;
	printf("%d\n",sizeof(s));
	printf("str   s:  %p\n",&s);
	printf("int   b:  %p\n",&(s.b));
	printf("char  c:  %p\n",&(s.c));
	printf("short d:  %p\n",&(s.d));
	printf("float e:  %p\n",&(s.e));
	printf("char  f:  %p\n",&(s.f));
	
	return 0;

}


运行结果为:

 

14
str   s:  0022FEE2
int   b:  0022FEE2
char  c:  0022FEE6
short d:  0022FEE8
float e:  0022FEEA
char  f:  0022FEEE


发生了改变,存储为 1111_10_11_1111_10    14byte

-------------------------------------------------------------分析----------------------------------------------------------- -----------------------------------------------------

#pragma pack ()的对其原则:

1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照

#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构

(或联合)最大数据成员长度中,比较小的那个进行。

结合1、2推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

根据这个原则再分析一下前面的测试代码。

 

#pragma pack (2)
typedef struct a
{
 int b; //int 4字节和2 取2个字节对齐 存储形式为 1111
 char c; //char 1字节和2 取1个字节对齐 存储形式为 1
 short d;//short 2个字节和2 取2个字节对齐 存储形式为 011
 float e;//float 4个字节和2 取2个字节对齐 存储形式为 11_11
 char f; //char  1个字节和2 取1个字节对齐 存储形式为 1
} st;

 

实际结构体内部的对齐方式 就是像上面写出的一样 1111 1011 1111 1 为13个字节

但是还有一个对齐及struct整体对齐,struct 最大成员字节为4 和2 取2个字节对齐 所以 最终为 1111 1011 1111 10 为14个字节

 

为了验证上面分析的正确性,再改变代码为1字节对齐,运行结果为:

12
str   s:  0022FEE4
int   b:  0022FEE4
char  c:  0022FEE8
short d:  0022FEE9
float e:  0022FEEB
char  f:  0022FEEF

1111_1_11_1111_1  12byte 成立

-----------------------------------------------------------------------------拓展-------------------------------------------------------------------------------

(1) MSDN中对于n的规定:

n(可选)

指定要用于封装的值(以字节为单位)。 如果没有为模块设置编译器选项 /Zpn 的默认值为 8。 有效值为 1、2、4、8 和 16。 成员将在作为 n 的倍数或成员的大小的倍数的边界(以较小者为准)上对齐。

(2) 还有一个关于struct中定义struct的例子可以看一下:

 

#pragma pack(8)
typedef struct s1{
short a;
long b;
} S1;


typedef struct s2{
char c;
S1 d;
long long e;
}S2;
#pragma pack()


s1  11_001111  8byte

s2  1_000000011001111_11111111   24byte

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值