最近看了好多,也编了好多C语言的浩强哥书后的题,总觉的很不爽,真的真的好怀念linux驱动的代码,好怀念那下划线,那结构体,虽然自己还很菜。
同时看了一遍陈正冲老师的C语言深度剖析,收益很多,又把唐老师的视频复习了一部分,感觉收获更多。

这阶段一直想写一篇博客,其实有好多东西,先写一下C语言中的内存对齐吧。

大家都知道,在C语言中定义一个变量,char是占用一个字节的,int占用四个字节,float占用四个字节,double占用八个字节,short占用两个字节,long int占用四个字节,long long神马的是64位机器用的,暂时不讨论。

上面说基本的数据类型所占用的字节数,程序的测试咱们printf一下(由于是菜鸟,所以咱们就不玩F8,F9的问题了)。程序如下:

#include<stdio.h>

int main(void)
{
char a;
short b;
int c;
long int d;
double e;
float f; printf ("%d,%d,%d,%d,%d,%d\n",sizeof (a),sizeof (b),sizeof (c),sizeof (d),sizeof (e),sizeof (f));
return 1;
}

好了,我们可以知道这些数据类型占用的字节空间了,那么现在提出一个问题。

struct student
{
short s;
long b;
}stu;

当我们以4字节的方式编译的时候,请问printf("%d",sizeof(stu));

我一直都认为这个打印的值是6,因为很明显嘛,short是两个字节的,long是四个字节的,所以打印出来的大小就是6个字节嘛。那好,请在VC下编译测试一下吧。

结果出来的是8!!!

出乎意料了,这就是内存对齐。

内存对齐的意义在于:处理器是以规定的字节数进行读取字节数的,我们编译的是以4字节读取字节数,这就是问题的所在。而且,读取的块的大小必须是2的N次幂。

下面我们解释一下,上面那个结构体打印出来的大小是8的原因。

原因:short类型占用两个字节,四个字节是一块的情况下,那么当一个short类型占用两个字节以后还剩下两个字节,但是接下来我们要存储的是四个字节的long型,如果按照打印六的话,那么我们的处理的取值将会蒙圈,所以实际上编译器把这两个数据分配的空间是short占用两个字节后空出两个字节的位置,这样完成了一个四个字节的块,然后接下来的一个long型占用四个字节,这样完成了两个块,所以我们打印出来的是8 。空说估计一会自己都晕了,所以画个图:

同时还要说一下内存的对齐的规则:

①必须要按照编译器指定的字节数进行读取,同时还要考虑怎么样才可以使编译器读取数据最快捷。

②另外最后占用的字节数必须是整个结构体中字节数最大数据类型的整数倍。

还有一些其他规则,下面再进行介绍。

一个结构体的问题差不多了吧?那么再看一个:

#include <stdio.h>

struct student
{
short s;
long b;
}stu1; struct teacher
{
char c;
struct student stu1;
double e;
}stu2; int main()
{
printf("%d,%d\n",sizeof(stu1),sizeof(stu2));
}

咱们还是打印,那么打印出来的是多少呢?

这里说个插曲,在VC中默认的是8位编译,这个时候打印出来的是8和24,在linux下的GCC编译,打印出来的是8和20 。一直认为VC是4位编译,所以走了一些弯路,后来使用宏条件判断才知道VC是4位编译。下面分别说一下这种结构体嵌套结构体的内存对齐。

上面说的是4位的,那么这里我们还说继续先说4位的。

打印20的原因:

先说一下第二个结构体的第一个成员char,占用的是一个字节。第一个结构体的第一个成员short占用两个字节,第二个成员占用四个字节。好了,暂停一下,我这个时候我就疑惑了,为什么char和short不在一个四字节的块中呢,这样编译器也可以按照四字节进行很快速的读取啊?但是这个时候应该考虑的是,第一个结构体已经被编译器分配好了一个完整的空间,所以这个short是不可以并到第一个结构体中的。回到主题,第一个char单独占用一个字节的四字节的块,第一个结构体占用连个四字节的块,double为8字节,占用两个四字节的块,最后占用的是五个四字节的块。所以打印20 。

上图:

下面说一下当按照8字节进行编译的时候打印出24的原因。(虽然是8字节进行编译的,但是读取的还是按照四个字节进行读取的,这样的话前面说的原则仍然成立。)

原因如下:第一个char占用了一个字节,但是按照8字节存储,按照4字节读取,所以char占用了8字节前面的4字节,后面的四个字节被short占用,这样也完成了处理器最快速度读取并且没有破坏第一个结构体的整体性。剩下的一个一个long占用了一个四字节,我的同学说这个八字节的块要空出来四个,因为不可以把后来的double拆开,但是我认为这么解释不是很合理,我也不清楚原因是什么,所以暂时搁置。

上图:

先说这么多吧,这里面还有一些小东西,太晚了,各位建军节快乐吧,我明天还要继续我苦逼的实训道路。

C语言中的内存对齐的更多相关文章

  1. C语言中的内存对齐问题

    问题 突然收到了一个问题: #include<stdio.h> #include <math.h> struct icd { int a; //4 char b; //1 do ...

  2. C语言中的内存压缩技术

    C语言中的内存压缩技术 前言 在整个研究生阶段我都在参与一个LTE协议栈实现的项目,在这个项目中,我们利用一个自己编写的有限状态机框架将协议栈中每一层实现为一个内核模块.我们知道,在编写内核代码时需要 ...

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

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

  4. C++继承体系中的内存对齐

    本篇随笔讨论一个比较冷门的知识,继承结构中内存对齐的问题,如今内存越来越大也越来越便宜,大部分人都已经不再关注内存对齐的问题了.但是作为一个有追求的技术人员,实现功能永远都是最基本的要求,把代码优化到 ...

  5. C语言中的内存分配与释放

    C语言中的内存分配与释放 对C语言一直都是抱着学习的态度,很多都不懂,今天突然被问道C语言的内存分配问题,说了一些自己知道的,但感觉回答的并不完善,所以才有这篇笔记,总结一下C语言中内存分配的主要内容 ...

  6. C语言中的内存管理

    开始陆续的发一下唐老师视频的笔记吧,顺便带一些正冲哥书的的内容.不能一下都发出来,因为内容发多了自己也受不了,而且发的都是学习视频时候的一些笔记,可能会有一些问题不是很清晰. 先说一下C语言中的内存管 ...

  7. C语言中动态内存分配的本质是什么?

    摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...

  8. windev中的内存机制及其与C语言中的内存指针相似性(一)

    windev中的内存机制,是初入windev世界必须要越过的一道高山,以下我的理解和经验未必都对,如有错误或遗漏,以后再纠正或补充!另外,以下内容,咱先谈应用,再说对机制的认识和理解. 一.新建表单, ...

  9. C语言中的内存相关问题

    内存是用来存储数据与程序的,对我们写程序来说非常重要.所以内存对程序来说几乎是本质需求.越简单的程序需要越少的内存,而越庞大越复杂的程序需要更多的内存. 注意:在嵌入式系统中有ROM和RAM两类内存, ...

随机推荐

  1. 3D数学学习笔记——笛卡尔坐标系

    本系列文章由birdlove1987编写.转载请注明出处. 文章链接: http://blog.csdn.net/zhurui_idea/article/details/24601215 1.3D数学 ...

  2. Android 4.4 KitKat NotificationManagerService使用具体解释与原理分析(一)__使用具体解释

    概况 Android在4.3的版本号中(即API 18)增加了NotificationListenerService,依据SDK的描写叙述(AndroidDeveloper)能够知道,当系统收到新的通 ...

  3. Is it always safe to call getClass() within the subclass constructor?(转)

    14down votefavorite   An article on classloading states that the method getClass() should not be cal ...

  4. SpringMVC注释启用

    这篇文章是我学习的网络视频SpringMVC写的过程. 谢谢公布各位前辈的视频 以下评论SpringMVC几个关键步骤,注意事项启用: 首先需要加载配置文件(假设请使用自定义路径) <? xml ...

  5. 正则获取URL参数

    一 获取指定URL参数 function getUrlParams(name) { var reg = new RegExp("(^|&)" + name + " ...

  6. char与byte差异

    很多人刚开始学习(包含I,我已经学会了一年多java该)肯会char和byte怀疑这两个数据类型,相互混淆.今天,大量的信息专门搜索,至byte和char两个数据类型进行了总结和比较.第一批成果与大家 ...

  7. [Shell]输入參数

    获取shell脚本的输入參数,而且推断得到的參数. #!/bin/bash #title: testPT.sh #atuhor: orangleliu #date: 2014-08-08 #desc: ...

  8. 如何构建高性能web网站:分布式缓存

    一.数据库前端缓冲区 要清除数据库前缓冲区,首先必须明确什么是文件系统的内核缓冲区(Buffer Area):它位于内核的物理内存地址空间,除了使用O_DIRECT比其他标签中打开文件,所有的磁盘的读 ...

  9. ASP.NET AJAX简明教程

     当我们谈论Ajax时,首先想到的就是JavaScript下的Ajax,用来完成网页的交互,局部刷新工作,Microsoft的ASP.NET AJAX框架在Web的开发中承担着类似的角色,并简化了Ja ...

  10. js中位运算的运用

    原文:js中位运算的运用 我们可能很少在编程中用位运算,如果没深入学习,可能也很难理解.平时的数值运算,其实是要先转换成二进制再进行运算的,而位运算就是直接进行二进制运算,所以位运算的执行效率肯定是更 ...