结构体深度剖析(内存对齐,对齐参数,偏移量)
来源:互联网 发布:mac 繁体转简体 编辑:程序博客网 时间:2024/06/03 05:08
一、了解结构体
在C语言中,除了最常见用数据类型,字符类型(char)、整数类型(short、int、long )、实型(float、double),,,,,,最常见也是最经典的还有一种数据类型,那就是结构体。
二、结构体经典面试题:
(1)、什么是结构体?
(2)、一般在什么情况下用到结构体?
(3)、什么是结构体内存对齐?为什么要对齐?怎样对齐?
(4)、对齐参数如何设置?可以设置为按照任意字节数对齐吗?
(5)、如何知道结构体某个成员相对于结构体起始位置的偏移量?
三、 下面,我们围绕以上提出的6个问题来解释结构体。
(1)、什么是结构体?
定义:结构体是一系列数据的集合这些数据可能描述了一个物体,也可能是对一个问题的抽象。举个栗子,简单的说,对于人,人有名字,性别,年龄,身高,体重等个人信息,那么,我们在定义这种个体的时候,就不能说它能用一个字符或整型变量来定义。 这时候,就需要结构体闪亮登场了。
for example 1:
struct people { char name[20]; int age; char gender[3]; float height; };
(2)、一般在什么情况下用到结构体?
a、一般当内置内存无法满足用户需要,没有合适类型对应对象时,需要封装特定的类型
b、当函数有多个参数时,返回值过多,需要封装特定类型,将参数打包返回。
(3)、什么是结构体内存对齐?为什么要对齐?怎样对齐?
结构体内存对齐:元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每个元素放置到内存中时,它都会认为内存是按照自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始。
for example2:
struct A { int a; char b; double c; char d; };
解析:
在windows系统32位平台上:
int占4个字节
char占1个字节
float占4个字节
double占8个字节
int a从0偏移开始,占四个字节,即占用0,1,2,3,现在可用偏移为4偏移,接下来存char b; 由于4是1的倍数,故而,b占用4偏移,接下来可用偏移为5偏移,接下来该存double c; 由于5不是8的倍数,所以向后偏移5,6,7,都不是8的倍数,偏移到8时,8是8的倍数,故而c从8处开始存储,占用8,9,10,11,12,13,14,15偏移,现在可用偏移为16偏移,最后该存char d ;因为16是1的倍数,故d占用16偏移,接下来在整体向后偏移一位,现处于17偏移,min(默认对齐参数,类型最大字节数)=8;因为17不是8的倍数,所以继续向后偏移18…23都不是8的倍数,到24偏移处时,28为8的整数倍,故而,该结构体大小为24个字节。
方法总结:
a、从零偏移处开始,按字节大小计算,判断此偏移地址是否为该成员变量和对齐参数两者之间的最小值,即min(对齐参数,sizeof()成员);
b、若是,则从此处开始占用内存,大小为该类型所占字节数值,若不是,则内存向后偏移到最小值整数倍处,再开始占用空间。
c、按a、b、两步骤算出结构体实际所占内存时,为了方便后面类型的存储,再向后偏移一位,然后判断该地址是否是默认对齐数与该结构体中最大类型所占字节数的最小值 ,即:min(默认对齐参数,类型最大字节数)的整数倍,若是,则当前偏移地址的字节数便是结构体大小,若不是,继续向后偏移,直至为最小值整数倍为止。
(4)、对齐参数如何设置?可以设置为按照任意字节数对齐吗?
解析:在windows中,VS编译器下,默认对齐数为8;
在Linux中,默认对齐数为4
设置对齐参数可在结构体struct之前加上#pragma pack(对齐数),在struct之后加上#pragma pack;便可以设置对齐参数。
for example3:
#pragma pack(4)struct A { int a; char b; double c; char d; };#pragma pack;
对齐参数不能任意设置,只能是内置类型已有的字节数,如:char(1)、short(2),int(4),double(8)…不能是3,5…任意数。
(5)、如何知道结构体某个成员相对于结构体起始位置的偏移量?
使用offsetof宏来判断结构体中成员的偏移地址。使用offsetof宏需要包含stddef.h头文件,该宏定义如下:
#define offsetof(type,menber) (size_t)&(((type*)0)->member)
巧妙之处在于将地址0强制转换为type类型的指针,从而定位到member在结构体中偏移位置,编译器认为0是一个有效的地址,从而认为0是type指针的起始地址。
到了这里,本文已接近尾声了,下篇博客将更新位段、联合以及大小端的相关知识详尽剖析,敬请期待。
- 结构体深度剖析(内存对齐,对齐参数,偏移量)
- 结构体内字节对齐偏移量
- C 深度剖析内存对齐
- 结构体对齐(内存对齐)
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐 结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐.结构体对齐
- 内存对齐(结构体)
- 四字节对齐,获取结构中元素的偏移量
- 结构体字节对齐---内存字节对齐(转载)
- [C++基础]内存对齐(字节对齐,结构体对齐)
- 关于内存对齐以及通过偏移获得结构地址
- POJ 3046 Ant Counting 题解- 多重集组合数问题(附测试数据)
- JDBC学习笔记—数据库连接池(DBCP和C3P0)
- 深入分析Java规范中JVM的内存布局模型
- 基于KNN的手写体识别和数码管数字识别
- 如何防止后台线程抛出的异常让程序崩溃退出
- 结构体深度剖析(内存对齐,对齐参数,偏移量)
- 数字信号中心频率
- JS代码中!!的用法,以及代码性能对比
- Codeforces Round #440 (Div. 2,)-数学&规律- Maximum splitting
- 模板..
- [Ybt 1351] 家谱树 ——拓扑排序
- 线程调度的方法2
- MyEclipse2014上传项目到github
- 字符串的交换,, 大神与我的作品有差距。等我成为了指针之王再来干他!!!!