问题引入

定义一个结构体的一般形式为:

struct 结构体名
{//类型说明符  成员名;
};

例如有如下结构体:

struct Stu
{int id;char sex;float hight;
};

那么一个这样的结构体变量占多大内存呢?也就是

cout<<sizeof(Stu)<<endl; 会输出什么?

在了解字节对齐方式之前想当然的会以为:sizeof(Stu) = sizeof(int)+sizeof(char)+sizeof(float) = 9.

然而事实并非如此!

字节对齐原则

在系统默认的对齐方式下:每个成员相对于这个结构体变量地址的偏移量正好是该成员类型所占字节的整数倍,且最终占用字节数为成员类型中最大占用字节数的整数倍

在这个例子中,id的偏移量为0(0=4*0),sex的偏移量为4(4=1*4),hight的偏移量为8(8=2*4),此时占用12字节,也同时满足12=3*4.所以sizeof(Stu)=12.

 (1)出现继承关系时:

struct A{int a;char b;
};
struct B:A{char c;int  d;long long e;
};

  基类的成员总是在派生类的前面。而且即使有字节对齐,基类对齐后派生类的成员不会占用基类填充的字节,即计算好基类所占字节数后,这些字节只能由基类拥有,不能被派生类的成员占用(即char b后面有3字节的填充,之后才有char c)在派生类中成员的分布只需满足每个变量起始字节序号为该类型所占字节数的整数倍且最终大小为占用字节数最大的类型对应的字节数的整数倍。排列如下:

/*0   4   8   12  16      24|   |   |   |   |       |aaaab---c---ddddeeeeeeee
*/

(2)出现关联关系时:

  必须满足:1.结构体/类与结构体/类之间不会共用自动补齐的内存,即一个结构体变量/对象对齐之后填补的内存不允许被其他变量/对象占用;2.结构体的起始字节位置必须是该结构体中所占字节数最大的变量的字节数的整数倍;3.最终所占字节数必须是最大所占字节数最大的变量的字节数的整数倍。

(3)出现强制对齐方式时:

  当然,有时候考虑到其他特殊用途,使用#pragma pack(n)来设定以n字节对齐的方式(n可取2的较小次幂,即1,2,4,8,具体取值范围以及默认值与所使用的编译器有关。笔者所测试的环境下vs/vc默认为8,gcc默认为4)。

n字节对齐就是说变量存放的起始地址的偏移量有两种情况:

第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式;

第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

比如有以下代码:

 1 #pragma pack(push) //保存对齐状态
 2 #pragma pack(4)//设定为4字节对齐
 3 struct Test
 4 {
 5     char c1;
 6     double d;
 7     int i;
 8     char c2;
 9 };
10 #pragma pack(pop)//恢复对齐状态

这时候编译器就会被迫使用我们约定的字节对齐方式,即4字节对齐,因此c1占4字节,d占8字节,i占4字节,c2占4字节,共20字节;

如果我们没有设置字节对齐方式,仍然使用默认对齐的话,这里sizeof(Test) = 24。

注:以上测试效果及完整代码见github.

最后一个问题,为什么要进行字节对齐?

  《Windows核心编程》里这样说:当CPU访问正确对齐的数据时,它的运行效率最高,当数据大小的数据模数的内存地址是0时,数据是对齐的。例如:WORD值应该是总是从被2除尽的地址开始,而DWORD值应该总是从被4除尽的地址开始,数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。

补充:C++类中的数据成员也遵循以上对齐原则,也就是说:

1.在不考虑(或者说在没有)虚函数和虚继承的情况下,sizeof(自定义类)也按照类似上面的方式来计算。

2.如果一个类拥有虚函数或者虚继承,则在数据成员的基础上相当于多一个指针类型的数据成员(位置在所有数据成员的前面),最后计算时加上即可。

3.如果一个类或者结构体不含有任何数据成员,且无虚函数以及虚继承,则sizeof()结果为1。

4.静态成员不在计算范围。

转载于:https://www.cnblogs.com/webary/p/4721017.html

struct/class等内存字节对齐问题详解相关推荐

  1. 程序人生 | C语言字节对齐问题详解 - 对齐/字节序/位序/网络序等(上)

    本文首发于 2014-07-21 15:32:28 1. 引言 考虑下面的结构体定义: typedef struct{char c1;short s; char c2; int i; }T_FOO; ...

  2. C语言字节对齐问题详解

    转载原文连接:https://www.cnblogs.com/clover-toeic/p/3853132.html C语言字节对齐问题详解 引言 考虑下面的结构体定义: 1 typedef stru ...

  3. c++内存中字节对齐问题详解

    一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这 ...

  4. C语言 字节对齐问题 详解

    一  什么是字节对齐 现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量.但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排 ...

  5. C语言字节对齐问题详解(zz)

    http://www.bubuko.com/infodetail-263205.html 引言 考虑下面的结构体定义: typedef struct{char c1;short s; char c2; ...

  6. c语言特殊字符字符串宽度对齐,[转]C语言字节对齐问题详解

    引言 考虑下面的结构体定义: 1 typedef struct{2 charc1;3 shorts;4 charc2;5 inti;6 }T_FOO; 假设这个结构体的成员在内存中是紧凑排列的,且c1 ...

  7. 更改结构体的内存字节对齐方式--经典

    结构体字节对齐 http://blog.163.com/ecy_fu/blog/static/4445126200910603739941/ http://hi.baidu.com/skyland_l ...

  8. C语言内存字节对齐小结

    在C语言面试和考试中经常会遇到内存字节对齐的问题.今天就来对字节对齐的知识进行小结一下. 首先说说为什么要对齐.为了提高效率,计算机从内存中取数据是按照一个固定长度的.以32位机为例,它每次取32个位 ...

  9. Hello C(八)——内存字节对齐

    一.内存字节对齐简介 1.内存字节对齐 计算机中内存空间都是按照字节划分的,从理论上讲对任何类型的变量的访问可以从任何地址开始,但是在程序实际编译过程中,编译器会对数据类型在编译过程中进行优化对齐,编 ...

  10. ptmalloc内存分配和回收详解(文字版)

    ptmalloc内存分配和回收详解(文字版) 进程默认内存布局(x86) 从进程的内存布局可知,.bss段之上的这块分配给用户程序的空间被称之为heap,start_brk指向heap的开始,而brk ...

最新文章

  1. 终于找到程序员无休止加班的原因了
  2. NCspider项目总结
  3. wsl设置c盘自动挂载到wsl中的/c/目录下
  4. Redis 哨兵Sentinel 文档
  5. NO--15 微信小程序,scroll-view选项卡和跳转
  6. java听课笔记(十五)之 网络编程
  7. 【洛谷P1378】油滴扩展
  8. I2C总线之(一)---概述
  9. ToString:身份哈希码的十六进制表示形式
  10. SecureCRT向多个tab窗口发命令
  11. 接口规范 6. 查看在线用户
  12. MySQL 第五次练习(MySQL备份恢复)
  13. ffmpeg结构体以及函数介绍(一)
  14. Python截屏工具,识别屏幕中的二维码
  15. 宣化上人:诸病从何来?
  16. 【Little Demo】从简单的Tab标签到Tab图片切换
  17. 论文管理工具:Zotero使用心得
  18. python从DataFrame中删除列
  19. 利用计算机传播淫秽物品,传播淫秽物品罪四个条件包括什么
  20. [分享]低工作电流超低功耗LCD液晶显示驱动芯片-VKL144A/VKL144B-TSSOP48/QFN48 6mm*6mm超小体积

热门文章

  1. leetcode 【 Sort Colors 】python 实现
  2. jqGrid Pager、Navigator和自定义按钮(转)
  3. 利用PROMPT_COMMAND记录每个用户执行命令的时间ip等信息。
  4. 网管必须熟悉的几个网络DOS命令
  5. 10000以内的素数。
  6. 你们要得SpringBoot版的停车管理系统(含小程序)已经找到了,改改就能卖钱(附源码)...
  7. 学会了这条 Curl 命令实用小技巧,网站故障秒排除!
  8. 鸿蒙os 实测,鸿蒙体验怎么样_鸿蒙OS实测体验
  9. 通讯录获取源码_[源码和文档分享]基于Java语言的C/S模式通讯录备份和查询软件...
  10. *第十六周*数据结构实践项目二【大数据集上排序算法性能的体验】