再谈sizeof——struct 结构存储空间的大小:与成员的顺序、#progma pack参数有关系

struct 结构存储空间的大小:与成员的顺序、#progma pack参数有关系

针对字节对齐,环境使用的gcc version 3.2.2编译器(32x86平台)为例。

 

char 长度为1个字节,short 长度为2个字节,int 长度为4个字节。

struct 子项在内存中的按顺序排列:

1)没有#progma pack(n)参数的情况,各个子项的对齐系数为自己长度。

2)有#progma pack(n)参数的情况,各子项的对齐系数为min(自己长度,n);

3)struct 整体的对其系数为子项对齐系数最大值

 

看下面的例子:

struct A{

char a;      //字长1对其系数1

char b;     //字长1对其系数1

char c;     //字长1对其系数1

};//整体对其系数为1

 sizeof(struct A)值是       

看下图

 

绿色为被填充的内存,黄色为空,因此sizeof(struct A)=3;

 

struct B {

    int a;           //对其系数4

    char b;       //对其系数1

    short c;     //对其系数2

};//整体对其系数4

sizeof(strcut B)值是      

如图

short c对其系数2必须和偶地址对齐,int a同理也与能4的倍数地址对其。

粉色内存被结构占用,因此sizeof(strcut B)=8

 

 

struct C {

    char b;   //对其系数1

    int a;      //对其系数4

    short c;  //对其系数2

};//整体对其系数4

sizeof(struct C)的值是     

如图

int a 从4的倍数地址开始,所以开始地址是4,因为结构整体对其系数为4,因此short c后的两个内存被占用,使大小为4的倍数。

sizeof(struct C)=12

 

#progma pack (2)

struct D {

    char b;    //对其系数min(长度=1,n=2)=1

    int a;       //对其系数min(长度=4,n=2)=2

    short c;   //对其系数min(长度=2,n=2)=2

};//整体对其系数2

sizeof(struct D)值是     

如图

 

#progma pack (2)  对int a的放置产生影响,

#progma pack (n)  只能取1、2、4

因此 sizeof(struct D)=8

 

以上转载自http://blog.163.com/feyeye@126/blog/static/4351010920091082551515/

 

字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
 
  1)  结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
 
  2)  结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal padding);
 
  3)  结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
 

 

指针变量p的sizeof

 
指针是记录了另一个对象的地址,既然是来存放地址的,那么它应该等于计算机内部地址总线的宽度。
 
所以在32位计算机中,一个指针变量的返回值必定是4(注意结果是以字节为单位),
 
可以预计在将来的64位系统中指针变量的sizeof结果为8。
 
char* pc = "abc";
int* pi;
string* ps;
char** ppc = &pc;
void (*pf)();//函数指针
sizeof( pc ); // 结果为4
sizeof( pi ); // 结果为4
sizeof( ps ); // 结果为4
sizeof( ppc ); // 结果为4
sizeof( pf );// 结果为4
指针变量的sizeof值与指针所指的对象没有任何关系,正是由于所有的指针变量所占内存大小相等,
 
所以MFC消息处理函数使用两个参数WPARAM、LPARAM就能传递各种复杂的消息结构(使用指向结构体的指针)。

 

sizeof(struct)大小

以下测试在gcc 版本 4.1.2 20070626 (Red Hat 4.1.2-14)

struct thread_arg
{
 int n_thread;
 char* sz_thread;
};

 struct thread_arg* st_value;

 printf("st_value = %d, thread_arg = %d\n",sizeof(st_value),sizeof(struct thread_arg));
 
 st_value=(struct thread_arg*)malloc(sizeof(struct thread_arg));
 int n_test1 = sizeof(*st_value);
 st_value->n_thread = 5;
 st_value->sz_thread = "hello kitty";
 int n_test2 = sizeof(*st_value);
 
 printf("test1 = %d, test2 = %d\n",n_test1,n_test2);

 

结果
st_value = 4, thread_arg = 8
test1 = 8, test2 = 8

为什么呢?指针肯定是4 不用质疑,而在结构体中int 4 指针也为4 所以为8

这是最初分配空间时错误的大小,st_value此时指针只有4字节,所以空间大小不对 ,可以写成*st_value
 st_value=(struct thread_arg*)malloc(sizeof(st_value));
 

结果
st_value = 4, thread_arg = 8
test1 = 8, test2 = 8

第一种分配的是8个字节的空间,而第二种是我写错后的指针的4个字节

最终的结果是一致的,其实这时候是越界的,其他内存空间可能已被破坏。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值