摘要:

经常被计算结构体的sizeof给搞晕,于是找了个时间,静下心来,搞定它。

一、为什么结构体计算这么乱?

答案是字节对齐,计算机存储系统中以Byte为单位存储数据,不同数据类型所占的空间不同,如:整型(int)数据占4个字节,字符型(char)数据占一个字 节,

短整型(short)数据占两个字节,等等。计算机为了快速的读写数据,默认情况下将数据存放在某个地址的起始位置,如:整型数据(int)默认存储 在地址能被

4整除的起始位置,字符型数据(char)可以存放在任何地址位置(被1整除),短整型(short)数据存储在地址能被2整除的起始位置。这样字节对齐有助于加快

计算机的取数速度,否则就得多花指令周期了。

二、字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:

1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

2. 结构体每个成员相对于结构体首地址的偏移量都是当前成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;

3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

说明:1、基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型;

2、对于复合数据类型,如结构体嵌套结构体,那么基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型;

3、我认为计算结构体大小的时候,主要用到准则2和准则3,对于准则1是编译器自动完成的,不需要过多理会。

4、C++中类的可以看做是特殊的结构体,所以类的sizeof的计算和结构体是一样的。

三、下面拿具体的程序来详细说明:

 // sizeof(结构体).cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include<iostream>
using namespace std; struct A
{
char a;
int b;
};
struct B
{
char a;
A a1;
char b;
};
int _tmain(int argc, _TCHAR* argv[])
{
cout<<sizeof(A)<<endl<<sizeof(B);
return ;
}

上述程序的输出结果是8和16.

下面结合前面给出的准则具体分析一下。

对于结构体A其基本成员类型有char和int两种,最宽的是int占用4个字节,那么根据准则1,编译器会自动为结果体A分配一个能被4整除的首地址,A的第一个成员char的首地址就是结构体A的首地址,即偏移量为0,接下来,下一个成员变量int首地址,如果不做处理的话,应该是相对于A的偏移量是1,这就不满足准则2了,所以编译器开始在char的后面填充3个字节,使得int相对于A的偏移量是4,来满足准则2,然后结构体的总大小就是1(char)+3(填充)+4(int)=8,同时满足了准则3,不用再填充了,所以sizeof(A)=8。

对于结构体B,其中包括了一个复合类型,查看基本类型的时候,要将其中的结构体A拆分成char和int两种类型来看,所以结构体B中的基本数据类型是char,char,int,char,最宽的数据类型是int,编译器会自动为B分配一个能被4整除的首地址,B的第一个成员char的首地址就是结构体B的首地址,即偏移量为0,接下来,下一个成员变量A的首地址,如果不做处理的话,应该是相对于B的偏移量是1,这就不满足准则2了,所以编译器开始在char的后面填充3个字节,使得成员A相对于所在结构体B的地址偏移量是4,来满足准则2,这时加上B的长度8,B中最后一个成员char相对于B来说地址偏移量是8,能满足准则2,所以不需要在A的后面填充字节,这时B的总长度是1(char)+3(填充)+8(A)+1(char)=13,不满足准则3,所以还需要在最后一个char后面再添加3个字节,最后得到B的总大小是1(char)+3(填充)+8(A)+1(char)+3(填充)=16,所以sizeof(B)=16。

sizeof(结构体)的计算的更多相关文章

  1. sizeof(结构体)和内存对齐以及位域

    Win32平台下的微软C编译器的对齐策略: 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除: 备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该 ...

  2. sizeof结构体

    规则1:结构体的对折长度为其基本数据成员的长度的最大值. 规则2:指定边界情况下,结构体的对折长度为自身对折长度和指定对折长度中较小者. 规则3:当行内结构体的基本数据成员的起始地址必须为其长度的整数 ...

  3. Problem D: 结构体:计算输入日期是该年的第几天

    #include <stdio.h> struct time{ int year; int month; int day;}; int main(void) { struct time s ...

  4. 结构体变量的sizeof计算

    结构体字节对齐准则: 1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除: 2. 结构体每个成员相对于结构体首地址的偏移量都是当前成员大小的整数倍,如有需要编译器会在成员之间加上填充字节: ...

  5. 全面总结sizeof的用法(定义、语法、指针变量、数组、结构体、类、联合体、位域位段)

    一.前言 编译环境是vs2010(32位). <span style="font-size:18px;">#include<iostream> #inclu ...

  6. 结构体,公用体,枚举类型的sizeof

    1)枚举类enum型空间计算 enum只是定义了一个常量集合,里面没有“元素”,而枚举类型是当做int来存储的,所以枚举类型的sizeof值都为4 enum color(red,pink,white, ...

  7. C++结构体中sizeof(1)

    sizeof sizeof操作符的作用是返回一个对象或类型名的长度,长度的单位是字节. 返回值的类型是标准库命名为size_t的类型,size_t类型定义在cstddef头文件中,该头文件是C标准库的 ...

  8. C++面试常见问题——13结构体与共用体的sizeof

    结构体与共用体的sizeof 结构体的sizeof 结构体变量占用的内存空间大小通常是其基本类型的大小,但是由例外(字节对齐机制) struct S1{ char c[5]; int a; doubl ...

  9. C语言中结构体对齐问题

    C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...

随机推荐

  1. JQuery 判断某个属性是否存在 hasAttr

    $(".fengye a").each(function () { if (typeof($(this).attr("href")) != "unde ...

  2. 【SQLite】使用事务处理带参数的插入

    using (SQLiteConnection conn = new SQLiteConnection(String.Format("Data Source={0};Pooling=true ...

  3. Jquery mobile 学习笔记

    最近学习移动开发,接触到了phonegap,然后又需要开始学习jquery mobile.掌握两者是开发轻应用的前提 在学习jquery mobile中,遇到了许多问题让初学者很是头疼,无意间找到这个 ...

  4. nginx如何实现404状态返回 200隐藏URL

    以http://WWW.cnblogs.COM为例: server        {                listen       80;                server_nam ...

  5. 自学JAVA总结

    2.在定义常量的时候C语言中定义为const而JAVA中为final3.在JAVA声明成员变量的时候,使用static来定义.4.在JAVA中的boolean类型只包括true和false,但是在C中 ...

  6. 统计网卡TX(发送)RX(接受)流量脚本

    显示网卡流量的方法蛮多,一般我们可以通过dstat来查看,但dstat不一定所有的机器都有安装.而我们知道,通过ifconfig可以看到某一网卡发送与接收的字节数,所以我们可以写一个脚本来统计一下. ...

  7. PS 颜色表大全-CMYK颜色表(2)

    CMYK颜色表 编号 C M Y K R G B 16进制值 1 0 100 100 45 139 0 22 8B0016 2 0 100 100 25 178 0 31 B2001F 3 0 100 ...

  8. java 构造函数

    1.public className(){}. 2.名称与类名相同,无返回值,无返回类型,void也不行.(就是上边的形式,除了可以有参数). 3.有0个或多个参数. 4.每个类都至少有一个const ...

  9. 【BZOJ 1412】[ZJOI2009]狼和羊的故事

    Description “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! O ...

  10. sql shard/partition

    sql http://www.infoq.com/news/2011/02/SQL-Sharding/ http://channel9.msdn.com/Shows/Data-Exposed/SqlD ...