详解struct、class中成员变量的字节对齐
2016-04-17 15:40
573 查看
看下面这个题目:
关于该题目的解释:
首先是要弄清楚是在64位平台下,其次考虑字节对齐!
第一:(粗略简要考虑)
在64位系统下,地址占64位,即指针占64位,8个字节
所以,*p所占的内存是这要的:
a:本身占1个字节,字节对齐占7个字节,共8个字节;
d:64位指针,占8字节;
b:占32位,4个字节;
c:16 :占16位,2个字节,字节对齐占2个字节,共4个字节;
e:64位,8个字节;
8 + 8 + 4 + 4 + 8 = 32。
第二:仔细考虑字节对齐的由来,精确每个变量的内存空间:
字节对齐:
1) 结构体的首地址 能够被 其最宽基本类型成员的大小 所整除;
2) 结构体每个成员 相对于 结构体首地址的偏移量 都是 该成员大小的整数倍,如有需要,编译器会在成员之间加上填充字节;(当成员大小大于处理器位数时,偏移量应该为系统中最宽类型成员大小的整数倍)
3) 结构体的总大小 为结构体 最宽基本类型成员大小 的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节。(如果结构体最大成员的大小大于处理器位数,侧结构体的总大小为系统中最宽类型成员大小的整数倍)
再来看这道题:
a占一个字节(注:地址为[0]);
d作为64位指针占8个字节(注:32位占四个字节,p也一样)(注:根据上面的准则2,d的偏移量要为8的整数倍,所以d的地址为[8]-[15],而非[1]-[8],下同);
b占了4个字节(注:地址为[16][19]);
c指定为16为,占了两个字节(注:地址为[20,21]);
e占8个字节,(同d的分析一样,e的地址应该为[24][31])。
所以A的答案应该是8,B的答案是32,C正确,D的答案为8。
利用VS工具查看(http://blog.csdn.net/songshimvp1/article/details/51253387):
(32位情况下)
再来看下面几个例子:
(1)
A1类的内存结构:
(2)调整一下成员顺序,再看一下:
A1类的内存结构:
(3)
(4)再来看一下继承中的情况:
从第二张图,我们可以看到类的内存结构完全印证了上述“字节对齐准则”!各个数据成员不一定得连续排列,由于边界调整可能就需要填补一些bytes(无论是在中间还是在末尾)。
(5)对比一下不同对齐方式下的内存结构:
A. 以4字节对齐:
B. 以8字节对齐:
( 结构体每个成员 相对于 结构体首地址的偏移量 都是 系统要求字节对齐位数 或者 该成员大小的整数倍)
关于该题目的解释:
首先是要弄清楚是在64位平台下,其次考虑字节对齐!
第一:(粗略简要考虑)
在64位系统下,地址占64位,即指针占64位,8个字节
所以,*p所占的内存是这要的:
a:本身占1个字节,字节对齐占7个字节,共8个字节;
d:64位指针,占8字节;
b:占32位,4个字节;
c:16 :占16位,2个字节,字节对齐占2个字节,共4个字节;
e:64位,8个字节;
8 + 8 + 4 + 4 + 8 = 32。
第二:仔细考虑字节对齐的由来,精确每个变量的内存空间:
字节对齐:
1) 结构体的首地址 能够被 其最宽基本类型成员的大小 所整除;
2) 结构体每个成员 相对于 结构体首地址的偏移量 都是 该成员大小的整数倍,如有需要,编译器会在成员之间加上填充字节;(当成员大小大于处理器位数时,偏移量应该为系统中最宽类型成员大小的整数倍)
3) 结构体的总大小 为结构体 最宽基本类型成员大小 的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节。(如果结构体最大成员的大小大于处理器位数,侧结构体的总大小为系统中最宽类型成员大小的整数倍)
再来看这道题:
a占一个字节(注:地址为[0]);
d作为64位指针占8个字节(注:32位占四个字节,p也一样)(注:根据上面的准则2,d的偏移量要为8的整数倍,所以d的地址为[8]-[15],而非[1]-[8],下同);
b占了4个字节(注:地址为[16][19]);
c指定为16为,占了两个字节(注:地址为[20,21]);
e占8个字节,(同d的分析一样,e的地址应该为[24][31])。
所以A的答案应该是8,B的答案是32,C正确,D的答案为8。
利用VS工具查看(http://blog.csdn.net/songshimvp1/article/details/51253387):
(32位情况下)
再来看下面几个例子:
(1)
class A1 { double d; int a; int b; char c; };
A1类的内存结构:
(2)调整一下成员顺序,再看一下:
class A1 { char c; int a; int b; double d; };
A1类的内存结构:
(3)
class Base { private: int val; char c1; char c2; char c3; };
(4)再来看一下继承中的情况:
class A { private: int val; char c1; }; class B:public A { private: char c2; }; class C :public B { private: char c3; };
从第二张图,我们可以看到类的内存结构完全印证了上述“字节对齐准则”!各个数据成员不一定得连续排列,由于边界调整可能就需要填补一些bytes(无论是在中间还是在末尾)。
(5)对比一下不同对齐方式下的内存结构:
A. 以4字节对齐:
B. 以8字节对齐:
( 结构体每个成员 相对于 结构体首地址的偏移量 都是 系统要求字节对齐位数 或者 该成员大小的整数倍)
相关文章推荐
- C#中struct和class的区别详解
- C++ 关于STL中sort()对struct排序的方法
- C# Struct的内存布局问题解答
- 深入C++中struct与class的区别分析
- 浅析c与c++中struct的区别
- c++中struct使用注意事项
- 深入解析C#编程中struct所定义的结构
- 浅析内存对齐与ANSI C中struct型数据的内存布局
- 教你5分钟轻松搞定内存字节对齐
- php读取二进制流(C语言结构体struct数据文件)的深入解析
- Go语言struct类型介绍
- 在Python的struct模块中进行数据格式转换的方法
- Python struct模块解析
- Go语言中struct的匿名属性特征实例分析
- nginx--C语言之对齐
- 优化结构体中元素的布局
- ext关于session失效的处理
- Python 10.4 struct
- typedef struct与struct的区别
- 内存对齐