首页
社区
课程
招聘
[原创]c语言结构体中的内存分配
发表于: 2015-12-28 21:26 6933

[原创]c语言结构体中的内存分配

2015-12-28 21:26
6933

问题导入::::

在结构中变量个数,变量类型相同,但顺序不同,观察结构分配空间的大小。

#include "stdafx.h"
#include<stdlib.h>
int _tmain(int argc, _TCHAR* argv[]){
        struct test{
                int a;
                char b;
                double c;

        };
        struct test1{
                int a;
                      double c;
                char b;

        };
        struct test2{
                double c;
                int a;
                char b;
        };
        printf("\n%d", sizeof(test));
        printf("\n%d", sizeof(test1));
        printf("\n%d", sizeof(test2));
        system("pause");
        return 0;
}
               
打印结果为:

                 test:16
              test:24
              test:16

由上边可以知道,即使是结构体中变量类型一致,但由于变量的大小不同,计算机在分配空间时做了其他的处理。

看  test  按我们的一般思维,int 4个字节 ,char 1个字节 ,double 8个字节  ,一共4+1+8=13个字节。可为什么结构体类型却有16字节的空间呢?

原来在面对结构体类型时,计算机为了对内存优化,提高存取速度,对字节进行对其处理,用空间换取了时间。

那么它是怎么对齐的呢!

首先:计算机给第一个结构体成员变量分配空间,什么类型给多大空间 ,第一个类型分配地址为0
             如 test中int  4个字节空间 我们用X来表示   
                    当前分配       XXXX

                 test2中double 8个字节空间
                      当前分配     XXXXXXXX
********************************************************************
《重要原则1》

     下边分配下一个类型空间:在分配时,看本次分配地址值,地址值必须为你当前要分配空间大小的整数倍 。
            如 test 中第一次分配4个字节空间,现在分配char类型 ,需要1个字节,地址为4 ,符合整倍数关系

                      当前分配    XXXX X    (为好区分,各类型分配空间以空格隔开表示)

           在test1 中 ,第二个类型 double 需要8个空间,地址为4,那么为了满足4是8的倍数关系,需要补齐空间,及从地址为8的空间开始给double 。
                        
                     当前分配: XXXXFFFF XXXXXXXX(F代表补齐的空间)

             在test2中    第一次分配了8个空间,地址到了8,是将要分配的int 4个字节的整数倍 所以正常分配即可

                  当前分配: XXXXXXXX XXXX
                       
****************************************************************
《重要步骤2》

以后的类型分配都是按上边那一步来进行。直到结束。

在结束时,计算机会对整个结构体空间大小检查,大小必须为结构体内最大变量类型大小的整数倍。不足补齐!

   (例1)  如test 中int  char  double 前两次分配到地址5,按《重要原则1》中,将要分配的double 8个字节,5不是8的倍数,补齐,
                       当前分配:

                                XXXX XFFF XXXXXXXX
     我们可以看到,对于test已经分配完了,这时对整个已经分配的大小做检查,一共分配了16个字节,最大字节为8 满足整数倍。因此不用平衡。

(例2)test1中int double char 前两个分配了16个空间,地址为16,char类型1个字节,则满足整数倍,
             当前分配:  XXXXFFFF XXXXXXXX X

test1中分配完了,我们做最后的检查,一共分了17个空间,最大分配为8个字节,不符合整数倍,那么就补齐,直到24个空间。所以,最终计算机给test1分配了24个字节

(例3)test2中double int char,前两一共分配12个空间,地址到12,即将分配到的char1个字节,是12的整数倍,可分配。

           当前分配:XXXXXXXX XXXX X

test2分配完成,最后整个空间检查 一共13个字节,最大分配8个字节,不是整数倍,补齐到16.
于是计算机最中给test2分配了16个字节。

********************************************************

这是对于常规的分配。当遇到结构体类型中包含结构体类型时,我们还要做些其他处理。

当结构体中还有结构体时,结构体包含的结构体第一个类型分配地址需满足所在的结构体成员最大类型大小的整数倍。

(时间所限 ,,,,,,)

如struct1中还有可struct2,那么当遇到要分配struct2中第一个类型空间时,判断struct2中成员最大的类型大小,要分配的地址必须为这个最大值的整数倍。具体点 ,如果struct2中第一个成员是int型  是4个字节,而struct2中还有double分配8个字节是最大的类型,那么在分配第一个int时,地址应为8的倍数。其他的按一般方式处理


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (14)
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
期待学习
2015-12-29 19:56
0
雪    币: 23
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
多练习就好
2015-12-29 20:25
0
雪    币: 144
活跃值: (31)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
4
还有看编译器对齐值什么的
2015-12-31 20:07
0
雪    币: 1140
活跃值: (102)
能力值: ( LV4,RANK:48 )
在线值:
发帖
回帖
粉丝
5
。我没太看懂
2016-1-2 20:07
0
雪    币: 9479
活跃值: (757)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不同编译器优化处理是不一样的,vc和gcc就不一样
2016-1-2 20:18
0
雪    币: 23
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
当编译器遇到结构体类型变量时,需要为其分配空间。由于结构体内成员变量类型不一致。为了取值的方便(我们知道计算机都是通过地址访问的,对齐了空间大小,就方便寻找)

对齐机制,就是第一个成员变量的“基址”为0,以后结构体内成员变量的地址都是相对第一个成员地址“0“的偏移量。记住,这地址不是实际地址,在这里我们是为了把分配问题说明白,才说某个“地址“是什么。比如说第一个变量实际地址为0XFFFDDD,那么我文章中计算出来的变量地址加上这个(第一个成员分配的地址)就是计算机实际分配的地址。

其实这就是个偏移量的问题。
2016-1-2 20:43
0
雪    币: 23
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢指正,我只道编译器不同编译器对类型分配大小不一样。我还没注意到在优化时也会有不同的处理。
2016-1-2 20:50
0
雪    币: 23
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
嗯嗯,11年注册的老大哥,多多指教。其实关于分配空间这个我也是刚接触,把自己学到的分享出来,大家讨论也是件很快乐的事。
2016-1-2 20:54
0
雪    币: 1363
活跃值: (139)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
搞清楚C语言的内存模型,对理解C语言提高很快,C的重点还是指针。
2016-1-3 21:08
0
雪    币: 23
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
嗯嗯,争取把指针这块的笔记尽量早点整理出来
2016-1-4 08:11
0
雪    币: 986
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
写的不错,受教受教
2016-1-5 13:41
0
雪    币: 23
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
队友的肯定就是最大的支持,谢谢
2016-1-17 10:24
0
雪    币: 980
活跃值: (1333)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
这个心得写得不错,能加上平台之间的差异就更好了
2016-4-14 21:44
0
雪    币: 775
活跃值: (3420)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
15
#pragma pack(1)
#pragma pack()
2016-4-15 09:21
0
游客
登录 | 注册 方可回帖
返回
//