当前位置: 首页 > news >正文

C语言中的内存对齐

最近看了好多,也编了好多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拆开,但是我认为这么解释不是很合理,我也不清楚原因是什么,所以暂时搁置。

上图:

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

 

相关文章:

  • Android开发之蓝牙Socket
  • shell中的||与的区别
  • Static简介
  • 解决WebService代理类速度慢的问题
  • centos6.5 mysql开机启动
  • Html 字体大小单位 px em pt
  • 如何调整 php 应用的上传附件大小?
  • Ubuntu14.10 更新源,现在很多源已经停用了建议使用ubuntu15以上
  • MVC3学习:实现简单的相册管理和图片管理
  • 彭旭老师《一线员工执行力提升训练》
  • 使用HTML5拍照
  • java基本数据类型
  • 中文锐推榜的优化
  • 如何下载vSphere Big Data Extensions 1.0免费试用版
  • Android深度探索读后感 第四章
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • [LeetCode] Wiggle Sort
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • Angular Elements 及其运作原理
  • JavaScript新鲜事·第5期
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • php中curl和soap方式请求服务超时问题
  • REST架构的思考
  • storm drpc实例
  • ucore操作系统实验笔记 - 重新理解中断
  • Vim Clutch | 面向脚踏板编程……
  • 后端_ThinkPHP5
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 基于遗传算法的优化问题求解
  • 开源SQL-on-Hadoop系统一览
  • 深入 Nginx 之配置篇
  • 走向全栈之MongoDB的使用
  • zabbix3.2监控linux磁盘IO
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​学习一下,什么是预包装食品?​
  • ###C语言程序设计-----C语言学习(6)#
  • #162 (Div. 2)
  • #include
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (c语言)strcpy函数用法
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (超详细)语音信号处理之特征提取
  • (正则)提取页面里的img标签
  • (转)人的集合论——移山之道
  • (转)视频码率,帧率和分辨率的联系与区别
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • ***利用Ms05002溢出找“肉鸡
  • *p++,*(p++),*++p,(*p)++区别?
  • .md即markdown文件的基本常用编写语法
  • .py文件应该怎样打开?
  • /var/lib/dpkg/lock 锁定问题
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • [ C++ ] STL---stack与queue