最近看了好多,也编了好多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. 《UNIX级别编程环境》注意读出信号(2)

    1.功能sigaction sigaction动与指定信号相关联的处理动作.其函数原型例如以下: #inlcude <signal.h> int sigaction(int signo,c ...

  2. unity3d 学习笔记_____Native2d 刚体、冲击、联合使用

    Mass Mass of the rigidbody. Linear Drag Drag coefficient affecting positional movement. Angular Drag ...

  3. 2机器学习实践笔记(k-最近邻)

    1:算法是简单的叙述说明 由于训练数据样本和标签,为测试数据的示例,从最近的距离k训练样本,此k练样本中所属类别最多的类即为该測试样本的预測标签. 简称kNN.通常k是不大于20的整数,这里的距离通常 ...

  4. javascript 中的location.pathname

    1 location.pathname; 这在之前我没怎么注意过,所以研究研究.location.pathname:返回URL的域名(域名IP)后的部分.例如 http://www.joymood.c ...

  5. RegisterStartupScript和RegisterClientScriptBlock区别

    RegisterStartupScript(key, script) RegisterClientScriptBlock(key, script) 这两个方法的作用都是从前台向后台写脚本,且都接受两个 ...

  6. crawler_爬虫_反爬虫策略

    关于反爬虫和恶意攻击的一些策略和思路   有时网站经常受到恶意spider攻击,疯狂抓取网站内容,对网站性能有较大影响. 下面我说说一些反恶意spider和spam的策略和思路. 1. 通过日志分析来 ...

  7. timesten备份和恢复

    ttIsql "DSN=ttwind;UID=cacheuser;PWD=cacheuser;OraclePWD=cacheuser;" --1.查看当前版本号 Command&g ...

  8. Swift语言指南(二)--语言基础之注释和分号

    原文:Swift语言指南(二)--语言基础之注释和分号 注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单 ...

  9. c# 官方命名规则

    官方的哦. https://msdn.microsoft.com/zh-cn/library/vstudio/ff926074(v=vs.110).aspx

  10. hdu 4932 Miaomiao&#39;s Geometry(暴力)

    题目链接:hdu 4932 Miaomiao's Geometry 题目大意:在x坐标上又若干个点,如今要用若干条相等长度的线段覆盖这些点,若一个点被一条线段覆盖,则必须在这条线的左端点或者是右端点, ...