结构体对齐那点事
来源:互联网 发布:centos 5.5 漏洞加固 编辑:程序博客网 时间:2024/06/05 08:08
struct example1{
char a;
double b;
long l;
};
struct example2{
char a;
long l;
double b;
};
大家算算结构体大小,初次接触的博友可能对答案有点惊讶,VC编译, sizeof后结果分别是:24,16。同样是的结构体,成员换了顺序,大小就不同了。其实内存对齐有个规则,只要知道了,就OK。那么以下5点是关键
1. 内存对齐与编译器设置有关,首先要搞清编译器这个默认值是多少
2. 如果不想编译器默认的话,可以通过#pragma pack(n)来指定按照n对齐
3. 每个结构体变量对齐,如果对齐参数n(编译器默认或者通过pragma指定)大于该变量所占字节数(m),那么就按照m对齐,内存偏移后的地址是m的倍数,否则是按照n对齐,内存偏移后的地址是n的倍数。也就是最小化长度规则
4. 结构体总大小: 对齐后的长度必须是成员中最大的对齐参数的整数倍。最大对齐参数是从第三步得到的。
5. 补充:如果结构体A中还要结构体B,那么B的对齐方式是选它里面最长的成员的对齐方式
所以计算结构体大小要走三步,首先确定是当前程序按照几对齐(参照1,2点),接着计算每个结构体变量的大小和偏移(参照3,5),最后计算结构体总大小(参照4)。
先算算example1吧,假设编译器是以16对齐的
1.确定按照几对齐: 16;
2.确定每个成员的偏移:a 占一个字节,16>1,按照1对齐,起始位置0,0%1 = 0,那么a就存在0位置;b占8个字节,16>8,按照8对齐,起始位置就不能是1了,因为要按照8对齐,所以最近的偏移起始位置是8, 8%8 =0, 那么b就存在位置8-15的位置;l占4个字节,16>4,按照4对齐,起始位置16, 16%4=0,那么l就存在位置16-19的位置。所以结构体从0到19一共占用20个字节
3.结构体总大小:成员中最大的对齐参数是b的8对齐,所以20%8!=0, 24刚好。
真的很搞!同理计算example2应该是16;
再举个结构体嵌套的例子吧,
#pragma pack(push)
#pragma pack(8)
struct test1{
int a;
char b;
int c[20]
long l;
} ;
struct test2{
char a1;
char a2;
struct test1 t1;
double b1;
}
#pragma pack(pop)
先计算test1, 8对齐,a占用0-3,b占用4,c占用8-87,l占用88-91,一共92个字节。成员中最大的对齐参数是int了92%4=0;
再计算test2, a1z占用0,a2占用1,t1呢,4 % 4 (test1里面最长的成员的对齐方式)= 0, 4-95,b1占96到103;一共104个字节,成员中最大的对齐参数是double了104%8=0;所以是104.
那关于我文章开头提到的那个文件转换,我现在只要知道原始程序是按照什么对齐的,然后在新程序中指定按照几对齐就可以了,哈哈!
挤时间写的,有的地方有遗漏,请各位指正!
// TestSizeof.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#pragma pack(show)//警告1warning C4810: 杂注 pack(show) 的值 == 8//#pragma pack(64)using namespace std;/* sizeof(),的作用是返回一个对象或者类型名的长度,单位是字节,*/struct A{int a;short b;} ;struct B{int a;double d;};int _tmain(int argc, _TCHAR* argv[]){int a=1;long b=2;double c=3.0;float d=3.3232;long long g=32;short s=2;char e='a';bool yes="true";char* ss1="123456789";char ss2[]="123456789";char ss3[20]="abc";char ss4[]="ab\n\0";char* ss5="ab\n\0\t" ;cout<<"int "<<sizeof(a)<<endl;cout<<"long "<<sizeof(b)<<endl;cout<<"double "<<sizeof(c)<<endl;cout<<"float "<<sizeof(d)<<endl;cout<<"short "<<sizeof(s)<<endl;cout<<"char "<<sizeof(e)<<endl;cout<<"long long "<<sizeof(g)<<endl;cout<<"bool "<<sizeof(yes)<<endl;cout<<"演示基本数据类型在win32系统中分别占多少位"<<endl;cout<<sizeof(ss1)<<endl;//ss1是字符指针,在win32系统下指针的大小是一个定值4.cout<<sizeof(ss2)<<endl;//ss2是一个数组,一个字符占位1个字节,但是最后要加上'\0',所以总共是10cout<<sizeof(ss3)<<endl;cout<<sizeof(ss4)<<endl;cout<<sizeof(ss5)<<endl;cout<<sizeof(A)<<endl;cout<<sizeof(B)<<endl;getchar();return 0;}
程序运行的结果:
- 结构体对齐那点事
- 结构体对齐那点事 熟练c/c++
- 内存对齐的那点事
- Java那点事——类加载器结构
- Java那点事——类加载器结构
- JVM内存结构、垃圾回收那点事
- 结构体对齐(内存对齐)
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐 结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 结构体对齐原理
- 结构体字节对齐
- vi查找命令
- html一些基础知识
- .htaccess实现301重定向
- OSB实战开发【三】部署 部署WebServices及其客户端应
- tiny6410基于SDBOOT通过NFS启动根文件系统
- 结构体对齐那点事
- (他山之石)MFC学习之路(一)VC MFC程序,在About对话框中获取并显示程序的版本号
- Java学习之路:不走弯路,就是捷径
- eclipse中server location为灰色,不能修改
- 学习心得之bash script
- Java 集合:HashSet 与 ArrayList
- ubuntu 安装svn
- Ubuntu9.10下怎样使用root登陆
- bluehost空间帐号被停的三大解决办法