问题引入

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

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.静态成员不在计算范围。

struct/class等内存字节对齐问题详解的更多相关文章

  1. [转]C语言字节对齐问题详解

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

  2. C++:struct和union 内存字节对齐问题

    转自:http://blog.csdn.net/wangyanguiyiyang/article/details/53312049 struct内存对齐问题 1:数据成员对齐规则:结构(struct) ...

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

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

  4. ARM字节对齐问题详解

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

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

    引言 考虑下面的结构体定义: typedef struct{ char c1; short s; char c2; int i; }T_FOO; 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始 ...

  6. C语言字节对齐问题详解(对齐、字节序、网络序等)

    首先说明一下,本文是转载自: http://www.cnblogs.com/clover-toeic/p/3853132.html 博客园用的少,不知道怎么发布转载文章,只能暂时这样了. 引言 考虑下 ...

  7. C语言字节对齐问题详解【转】

    引言 转自:http://www.cnblogs.com/clover-toeic/p/3853132.html 考虑下面的结构体定义: 1 typedef struct{ 2 char c1; 3 ...

  8. c语言,内存字节对齐

    引用:内存字节对齐 写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢?讲讲字节对齐吧. /************* ...

  9. C++内存字节对齐规则

    为什么要进行内存对齐以及对齐规则 C/C++—— 内存字节对齐规则 C++内存字节对齐规则

随机推荐

  1. MySQL C API概述

    以下列表总结了C API中可用的功能.有关更多详细信息,请参见 第27.8.7节“C API函数描述”中的说明. my_init():在线程安全程序中初始化全局变量和线程处理程序 mysql_affe ...

  2. IIS7.5配置过程

    1.Windows功能,注意选择应用程序开发功能,否则不能使用经典模式. 2.Cmd运行(使用.netframework4.0)C:\Windows\Microsoft.NET\Framework\V ...

  3. 使用 JS 实现图片左右跑马灯

    Ø  前言 之前写了一篇使用 JS 实现文字上下跑马灯,现在乘热打铁在把图片左右跑马灯一起贴出来,不多说直接看代码. 1.   首先定义 css 样式 <style type="tex ...

  4. php与java通用AES加密解密算法

    AES指高级加密标准(Advanced Encryption Standard),是当前最流行的一种密码算法,在web应用开发,特别是对外提供接口时经常会用到,下面是我整理的一套php与java通用的 ...

  5. 服务器中同一个【ip:port】可以多次accept的问题

    一.多次bind的问题 服务器的[ip:port]被某套接字绑定成功后,在该绑定解除之前,同一个[ip:port],不能再次被其他套接字绑定,否则绑定失败 二.多次accept的问题 有外来连接时,若 ...

  6. talk命令帮助文档(ubuntu 18.04)

    TALK() BSD General Commands Manual TALK() NAME talk — talk to another user SYNOPSIS talk person [tty ...

  7. oracle pivot

    select * from (select a.drugname, a.drugform, a.drugspec, a.type flag, max(a.maxzjprice) maxprice, m ...

  8. A - 签到题

    给定一个长度为N的数组A=[A1, A2, ... AN],已知其中每个元素Ai的值都只可能是1, 2或者3. 请求出有多少下标三元组(i, j, k)满足1 ≤ i < j < k ≤ ...

  9. Codeforces 1043F(容斥+dp)

    题目链接 题意 是否存在选择方案使所选的数$gcd=1$ 思路 $f[i][j]$表示选$i$个数$gcd=j$的方案数,$cnt[i]$表示包含因子$i$的数的个数,则$f[i][j]=$$C_{c ...

  10. java.lang.NoSuchMethodError: org.apache.curator.framework.api.CreateBuilder.creatingParentsIfNeeded()Lorg/apache/curator/framework/api/ProtectACLCreateModeStatPathAndBytesable;

    1 错误信息 java.lang.NoSuchMethodError: org.apache.curator.framework.api.CreateBuilder.creatingParentsIf ...