C/C++ sizeof函数解析——解决sizeof求结构体大小的问题

C/C++中不同数据类型所占用的内存大小

32位                 64位

char               1                    1

int                  4             大多数4,少数8

short              2                    2

long               4                    8

float               4                    4

double            8                    8

指针                    4                         8

(单位都为字节)

结构体(struct):比较复杂,对齐问题。

联合(union):所有成员中最长的。

枚举(enum):根据数据类型。

sizeof计算单层结构体大小

  运算符sizeof可以计算出给定类型的大小,对于32位系统来说,sizeof(char) = 1; sizeof(int) = 4。基本数据类型的大小很好计算,我们来看一下如何计算构造数据类型的大小。

C语言中的构造数据类型有三种:数组、结构体和共用体。

 数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘上元素的个数

结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。看下面这样的一个结构体:

struct stu1
{
     int i;
     char c;
     int j;
};  

用sizeof求该结构体的大小,发现值为12。int占4个字节,char占1个字节,结果应该是9个字节才对啊,为什么呢?

先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。

然而,在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则

      (1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 

      (2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。

再来看另外一个例子:

struct stu2
{
      int k;
      short t;
};  

   成员k的偏移量为0;成员t的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员k大小的整数倍。因此,编译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。

由此可见,结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小

对比下面两种定义顺序:

struct stu3
{
       char c1;
       int i;
       char c2;
}
struct stu4
{
       char c1;
       char c2;
       int i;
 }  

  虽然结构体stu3和stu4中成员都一样,但sizeof(struct stu3)的值为12而sizeof(struct stu4)的值为8。

sizeof计算嵌套的结构体大小

对于嵌套的结构体需要将其展开。对结构体求sizeof时,上述两种原则变为:

       (1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。

       (2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

看下面的例子:

struct stu5
{
      short i;
      struct
      {
           char c;
           int j;
      } ss;
      int k;
}  

  结构体stu5的成员ss.c的偏移量应该是4,而不是2。整个结构体大小应该是16。

下述代码测试原则2:

struct stu5
{
      char i;
      struct
      {
           char c;
           int j;
      } ss;
      char a;
      char b;
      char d;
      char e;
      char f;
}  

  结构体ss单独计算占用空间为8,而stu5的sizeof则是20,不是8的整数倍,这说明在计算sizeof(stu5)时,将嵌套的结构体ss展开了,这样stu5中最大的成员为ss.j,占用4个字节,20为4的整数倍。如果将ss当做一个整体,结果应该是24了。

另一个特殊的例子是结构体中包含数组,其sizeof应当和处理嵌套结构体一样,将其展开,如下例子:

struct ss
{
    float f;
    char p;
    int adf[3];
};   

  其值为20。float占4个字节,到char p时偏移量为4,p占一个字节,到int adf[3]时偏移量为5,扩展为int的整数倍,而非int adf[3]的整数倍,这样偏移量变为8,而不是12。结果是8+12=20,是最大成员float或int的大小的整数倍。

如何给结构体变量分配空间由编译器决定,以上情况针对的是Linux下的GCC。在Windows下的VC平台也是这样,至于其他平台,可能会有不同的处理。

  致谢:感谢您的耐心阅读!

时间: 2024-08-10 14:11:25

C/C++ sizeof函数解析——解决sizeof求结构体大小的问题的相关文章

结构体大小求值

 内存对齐概念,struct例子: struct stu{ char a; intb; char c; double d; char e; } 取pack(n),n,取结构体中最大成员大小m,取两个小值k, k = m< n?m:n; 取每个成员大小p,依次同k比较,取小值q = k< p?k:p; 第二步当中依次取得的值,即为内对齐标准,所谓的对齐,即此处的地址可被q整除. K值可作为外部对齐补0的依据. 当有数组的时候拆散了当普通变量存储. 下面开始计算结构体中的大小 取k值.(取pa

【C++】sizeof()函数解析

[1] 常见数据类型的的sizeof函数得出的值表 char int short long float double 指针 32 bit 1 4 2 4 4 8 4 64 bit 1 4 or 8 2 8 4 8 8 [2] 数组求sizeof 的值 数组的大小 = 数组中元素的个数 x 该类型的大小 [3] union 求 sizeof 的值 由于 union 中存在复写现象,union 结构的 sizeof 的值即为 union 中最大的元素的大小.例如: union student{   

sizeof进行结构体大小的判断

typedef struct{    int a;    char b;}A_t;typedef struct{    int a;    char b;    char c;}B_t;typedef struct{    char a;    int b;    char c;}C_t;void main(){    char*a=0;    cout<<sizeof(a)<<endl;//4    cout<<sizeof(*a)<<endl;//1--

hdu 1536 S-Nim 博弈论,,求出SG&#39;函数就可以解决

S-Nim Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4975    Accepted Submission(s): 2141 Problem Description Arthur and his sister Caroll have been playing a game called Nim for some time now

sizeof函数详解

原文链接http://blog.csdn.net/wzy198852/article/details/7246836 sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着“辛苦我一个,幸福千万人”的伟大思想,我决定将其尽可能详细的总结一下.但当我总结的时候才发现,这个问题既可以简单,又可以复杂,所以本文有的地方并不适合初学者,甚至都没有必要大作文章.但如果你想“知其然,更知其所以然”的话,那么这篇文章对你或许有所帮助.菜鸟我对C++的掌握尚未深入,其中不乏错误,欢迎各

SIZEOF函数使用

参考  http://blog.csdn.net/wzy198852/article/details/7246836 1.语法 sizeof有三种语法形式,如下:1) sizeof( object ); // sizeof( 对象 );2) sizeof( type_name ); // sizeof( 类型 );3) sizeof object; // sizeof 对象; 2.计算 1)计算求值 sizeof(2) = sizeof(int); sizeof(2.22) = sizeof(d

C语言 sizeof函数详解

1. 定义:sizeof是何方神圣sizeof乃C/C++中的一个操作符(operator)是也,简单的说其作用就是返回一个对象或者类型所占的内存字节数.MSDN上的解释为:The sizeof keyword gives the amount of storage, in bytes, associated with avariable or a type (including aggregate types). This keyword returns a value of type siz

sizeof函数总结

sizeof函数功能:计算数据空间的字节数 1.与strlen()比较 strlen计算字符数组的字符数,以"\0"为结束判断,不计算为'\0'的数组元素. sizeof计算数据(包括数组.变量.类型.结构体等)所占内存空间,用字节数表示(当然用在字符数组计算"\0"的大小). 2.指针与静态数组的sizeof操作 指针均可看为变量类型的一种.所有指针变量的sizeof 操作结果均为4. 实例1::char *p; sizeof(p)=4; sizeof(*p) =

含有虚函数的类sizeof大小

#include <iostream> using namespace std; class Base1{ virtual void fun1(){} virtual void fun11(){} public: virtual ~Base1(); }; class Base2{ virtual void fun2(){} }; class DerivedFromOne: public Base2 { virtual void fun2(){} virtual void fun22(){} }