精华内容
下载资源
问答
  • 为什么内存对齐?

    2021-01-08 22:47:13
    首先:内存是以字节为单位,但是处理器并不会按照一个字节为单位存取内存。它一般会以双字节,四字节,8字节,16字节甚至32字节为单位存取内存,我们将上述这些存取单位称为内存存取粒度。对于现代计算机硬件来说,...

    为什么要内存对齐?

    首先:内存是以字节为单位,但是处理器并不会按照一个字节为单位去存取内存。它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存,我们将上述这些存取单位称为内存存取粒度。对于现代计算机硬件来说,内存只能通过特定的对齐地址(比如按照机器字)进行访问。举个例子来说,比如在64位的机器上,不管我们是要读取第0个字节还是要读取第1个字节,在硬件上传输的信号都是一样的。因为它都会把地址0到地址7,这8个字节全部读到CPU,只是当我们是需要读取第0个字节时,丢掉后面7个字节,当我们是需要读取第1个字节,丢掉第1个和后面6个字节。

    假如没有使用内存对齐:

    一个整型变量(4 字节),他可以按照任意的起始地址存放,假设现在有一块内存单元:地址从 0~7. 这个整型变量从 地址为 1 的位置开始占据了 1,2,3,4 这 4 个字节. 现在处理器需要读取这个整型变量.由于处理器是 4 字节 4 字节的读取,所以从 0 开始读读取 0,1,2,3发现并没有读完整这个变量,那么需要再读一次,读取 4,5,6,7. 然后对两次读取的结果进行处理,提取出 1,2,3,4 地址的内容.

    当我们要读取的字节刚好落在两个机器字(机器字长是指计算机进行一次整数运算所能处理的二进制数据的位数)内时,就出现两次访问内存的情况,同时通过一些逻辑计算才能得到最终的结果。因此,为了更好的提升性能,我们须尽量将结构体做到机器字(或倍数)对齐,而结构体中一些频繁访问的字段也尽量安排在机器字对齐的位置。

    转载自:https://xiaozhuanlan.com/topic/3218694705

    展开全文
  • 我们都知道计算机是以字节(Byte)为单位划分的,但是大部分处理器并不是按字节块来存取内存的。它一般会以2字节,4字节,8字节,16字节甚至32字节为单位存取内存。 32位系统下,int占4byte,char占一个byte,那么将...

    我们都知道计算机是以字节(Byte)为单位划分的,但是大部分处理器并不是按字节块来存取内存的。它一般会以2字节,4字节,8字节,16字节甚至32字节为单位来存取内存。

    32位系统下,int占4byte,char占一个byte,那么将它们放到一个结构体中应该占4+1=5byte?实际上,通过运行程序得到的结果是8 byte,这就是内存对齐所导致的。下面我们来介绍什么是内存对齐?

    对齐准则

    1、char 1 字节对齐 ,即存放 char 型的变量,内存单元的编号是 1 的倍数即可。
    2、short int 2 字节对齐 ,即存放 short int 型的变量,起始内存单元的编号是 2 的倍数即可。
    3、int 4 字节对齐 ,即存放 int 型的变量,起始内存单元的编号是 4 的倍数即可
    4、long int 在 32 位平台下,4 字节对齐 ,即存放 long int 型的变量,起始内存单元的编号是 4 的倍数即可 。
    5、float 4 字节对齐 ,即存放 float 型的变量,起始内存单元的编号是 4 的倍数即可
    6、double
    vc 环境下, 8 字节对齐,即存放 double 型变量的起始地址,必须是 8 的倍数,double 变量占 8 字节
    gcc 环境下, 4 字节对齐,即存放 double 型变量的起始地址,必须是 4 的倍数,double 变量占 8 字节。

    在32位和64位的机器上,size_t的大小不同,如果在centos7上运行32位程序,我们需要安装

    yum -y install gcc-multilib g+±multilib

    通过一个小例子来说明是如何对齐的。

    #include <stdio.h>
    struct 
    {
    	char a;
    	int b;
    	char c;
    
    }s1;
    
    /*
    gcc -m32 test.c -o test
    g++ -m32 test.cpp -o test
     */
    
    int main(int argc, char const *argv[])
    {
    	
    	printf("%d\n",sizeof(s1));
    
    	return 0;
    }
    

    运行:

    在这里插入图片描述

    编译成32位程序并运行,32位默认4字节对齐,可以看到,结构体test 的大小为12字节(a占1字节,b占4字节,c占1字节),而不是6字节。

    下面下图:

    在这里插入图片描述
    上面的结构体,我们是不是可以考虑这样写:

    struct 
    {
    	int a;
    	char b;
    	char c;
    
    }s1;
    

    结构体变量大小是,它所有成员之和。 因为结构体变量是所有成员的集合。结构体变量分配内存的时候,是规则的。

    给结构体变量分配内存的时候,会去结构体变量中找基本类型的成员哪个基本类型的成员占字节数多,就以它大小为单位开辟内存,

    在 gcc 中出现了 double 类型例外

    1、成员中只有 char 型数据 ,以 1 字节为单位开辟内存。
    2、成员中出现了 short int 类型数据,没有更大字节数的基本类型数据。
    以 2 字节为单位开辟内存
    3、出现了 int float 没有更大字节的基本类型数据的时候以 4 字节为单位开辟内存。
    4、出现了 double 类型的数据
    情况 1:在 vc 里,以 8 字节为单位开辟内存。
    情况 2:在 gcc 里,以 4 字节为单位开辟内存。 无论是那种环境,double 型变量,占 8 字节。

    注意: 如果在结构体中出现了数组,数组可以看成多个变量的集合。 如果出现指针的话,没有占字节数更大的类型的,以 4 字节为单位开辟内存。 在内存中存储结构体成员的时候,按定义的结构体成员的顺序存储。

    啊哈!这里忘了说,使用union时,要留意平台的大小端问题。

    百度百科——大小端模式

    大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

    小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

    怎么获知自己使用的平台的大小端?Linux有个方法:

     #include <stdio.h>
    
     static union 
     {  
     	char c[4];  
     	unsigned long l;  
     }endian_test = { { 'l', '?', '?', 'b' } }; 
    
     #define ENDIANNESS ((char)endian_test.l)
    
    int main(int argc, char const *argv[])
    {
    	 printf("ENDIANNESS: %c\n", ENDIANNESS);
    	return 0;
    }
    

    编译运行:

    在这里插入图片描述

    可以看出我的虚拟机是小端。

    为什么要内存对齐?

    从上面的结构体来看,本来只需要6字节的空间,最后却占用了12字节,很明显浪费了空间。为什么要内存对齐,简单的说内存对齐能够提高 cpu 读取数据的速度,减少 cpu 访问数据的出错性。

    现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放。

    #pragma pack的作用

    #pragma pack 的主要作用就是改变编译器的内存对齐方式。不同平台上编译器的 pragma pack 默认值不同。而我们可以通过预编译命令#pragma pack(n), n= 1,2,4,8,16来改变对齐系数。

    #include <stdio.h>
    
    #pragma pack (1) /*指定按1字节对齐*/
    
    struct D
    {
    	char a;
    	int b;
    	short c;
    };
    #pragma pack () /*取消指定对齐,恢复缺省对齐*/
    
    int main(int argc, char const *argv[])
    {
    	printf("%d\n", sizeof(struct D));
    	return 0;
    }
    
    

    运行:
    在这里插入图片描述

    运行结果是7,上面的例子,应该对内存对齐有了全面的认识和了解,在以后的编码中定义结构体时需要考虑成员变量定义的先后顺序了。

    总结

    为了速度和正确性,请对齐你的数据。

    1、结构体的内存对齐,按照其内部最大元素基本类型或者模数大小对齐。
    2、模数在不同平台值不一样,也可通过#pragma pack(n)方式去改变。
    3、结构体的内存大小,并非其内部元素大小之和。

    在这里插入图片描述
    欢迎关注微信公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下:

    在这里插入图片描述

    展开全文
  • 内存对齐

    2020-04-21 21:19:51
    硬件平台限制,内存以字节为单位,不同硬件平台不一定支持任何内存地址的存取,一般可能双字节、4字节等为单位存取内存,为了保证处理器正确存取数据,需要进行内存对齐。 提高CPU内存访问速度,一般处理器的内存...

    为什么要内存对齐?

    1. 硬件平台限制,内存以字节为单位,不同硬件平台不一定支持任何内存地址的存取,一般可能以双字节、4字节等为单位存取内存,为了保证处理器正确存取数据,需要进行内存对齐。
    2. 提高CPU内存访问速度,一般处理器的内存存取粒度都是N的整数倍,假如访问N大小的数据,没有进行内存对齐,有可能就需要两次访问才可以读取出数据,而进行内存对齐可以一次性把数据全部读取出来,提高效率。

    内存对齐规则

    1. 数据成员对齐规则:struct或者union的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员都按照#pragma pack数值和这个数据成员自身大小中更小的那个进行对齐。

    2. 整体对齐规则:struct或者union的首地址按照内部最大数据成员的大小和#pragma pack数值较小的那个N进行对齐,并且结构体的总大小为N的整数倍,如有必要编译器也会在最后一个成员后面填充一些字节用于对齐。

    展开全文
  • 内存对齐原因和规则

    2020-11-05 23:28:33
    尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位存取内存,我们将上述这些存取单位称为内存存取粒度. 现在考虑4字节存取粒度的处理器...

    1.为什么要内存对齐?

    尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存,我们将上述这些存取单位称为内存存取粒度.

    现在考虑4字节存取粒度的处理器取int类型变量(32位系统),该处理器只能从地址为4的倍数的内存开始读取数据。

    假如没有内存对齐机制,数据可以任意存放,现在一个int变量存放在从地址1开始的联系四个字节地址中,该处理器去取数据时,要先从0地址开始读取第一个4字节块,剔除不想要的字节(0地址),然后从地址4开始读取下一个4字节块,同样剔除不要的数据(5,6,7地址),最后留下的两块数据合并放入寄存器.这需要做很多工作.
    在这里插入图片描述
    现在有了内存对齐的,int类型数据只能存放在按照对齐规则的内存中,比如说0地址开始的内存。那么现在该处理器在取数据时一次性就能将数据读出来了,而且不需要做额外的操作,提高了效率。
    在这里插入图片描述

    2.对齐规则

    每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。gcc中默认#pragma pack(4),可以通过预编译命令#pragma pack(n),n = 1,2,4,8,16来改变这一系数。

    有效对其值:是给定值#pragma pack(n)和结构体中最长数据类型长度较小的那个。有效对齐值也叫对齐单位。

    了解了上面的概念后,我们现在可以来看看内存对齐需要遵循的规则:

    (1) 结构体第一个成员的偏移量(offset)为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小对齐单位中较小那个的整数倍,如有需要编译器会在成员之间加上填充字节。

    (2) 结构体的总大小对齐单位整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
    举例:

    #pragma pack(4)  //32位
    
    struct x1
    {
        char c1;  
        int i;    
        char c2;  
    };
    struct x2
    {
    	char a;
    	float c;
    	double d;
    	bool b;
    };
    int main()
    {
        x2 test[10];
        printf("%d\n",sizeof(x1));  // 输出 12
        printf("%d\n",sizeof(test));  // 输出200
        return 0;
    }
    

    #pragma pack(4),且结构体中最长的数据类型为4个字节,所以有效对齐单位为4字节,下面根据上面所说的规则以s2来分析其内存布局:

    首先使用规则1,对成员变量进行对齐:

    sizeof(c1) = 1 <= 4(有效对齐位),按照1字节对齐,占用第0单元;

    sizeof(i) = 4 <= 4(有效对齐位),相对于结构体首地址的偏移要为4的倍数,占用第4,5,6,7单元;

    sizeof(c2) = 1 <= 4(有效对齐位),相对于结构体首地址的偏移要为1的倍数,占用第8单元;

    然后使用规则2,对结构体整体进行对齐:

    s2中变量i占用内存最大占4字节,而有效对齐单位也为4字节,两者较小值就是4字节。因此整体也是按照4字节对齐。由规则1得到s2占9个字节,此处再按照规则2进行整体的4字节对齐,所以整个结构体占用12个字节。

    根据上面的分析,不难得出上面例子三个结构体的内存布局如下:
    在这里插入图片描述
    同理:x2的pragma pack是4,最长类型是8,double。对齐单位是min(4,8),为4;应用规则1和规则2,得知x2的大小是20,所以数组test是200字节。

    展开全文
  • 硬件平台限制,内存以字节为单位,不同硬件平台不一定支持任何内存地址的存取,一般可能双字节、4字节等为单位存取内存,为了保证处理器正确存取数据,需要进行内存对齐。 提高CPU内存访问速度,一般处理器的内存...
  • C/C++内存对齐操作

    2021-04-14 22:07:22
    目录什么是内存对齐为什么要进行内存对齐如何进行内存对齐1.通过编译器来指定对齐长度2....尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至3
  • OC底层内存对齐--2

    2021-06-09 18:09:28
    通常内存是由一个个字节组成,cpu在存取数据时,并不是以字节为单位存储,而是以块为单位存取,块大小为内存存取力度。频繁存取字节未对齐数据,会极大降低cpu性能,所以可以通过减少存取次数来降低cpu...
  • linuxc/c++内存对齐

    2021-04-19 21:47:08
    尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位存取内存。 现在考虑4字节存取粒度的处理器取int类型变量(32位系统),该处理器只能...
  • 数据线通常都是复用,所以通常存取是以为单位(nor flash带有RAM接口,有足够地址线来寻址, 所以可以访问内存中每一个字节) 这导致了,nand flash不可以片内执行程序(nor flash可以,因为他能存取内存...
  • 首先我们需要明白这篇博客适用场景:对于B为单位短消息频繁落盘,文件落盘时间关乎系统运行效率。 消息落盘指的是数据从内存写入物理磁盘上,数据在内存存取效率速度比写盘快N多倍,如果我们需要优化...
  • 内存处理编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的...
  • javaweb之地址和编码

    2018-04-14 15:08:34
    在计算机科学中,内存中每个用于数据存取的基本单位,都被赋予一个唯一序号,称为地址,也叫做内存地址。内存地址指系统 RAM 中特定位置,通常十六进制数字表示。IP地址指互联网协议地址(英语:Internet...
  • 其实我们知道,cpu从外存取数据到内存是以基本单位的,也就是说cpu取一块连续地址到内存内,这样说话是不是对数组友好点?因为数组用连续地址存储着相同类型数据。但是在我考虑在实际应用中,如果需要...
  • (3)速度和容量“时空”矛盾,虛存量“扩大”是以牺牲CPU工作时间以及内外存交换时间代价。 •存储管理目的及功能 目的是方便用户,提高内存资源利用率,实现内存共享。 功能主要有...
  • 下面的代码输出是什么为什么? 1、sizeof()和strlen()的使用? 答: 1.从功能定义上,strlen函数,用来求字符串的长度,sizeof函数用来求指定变量或变量类型等所占用内存的 大小; 2.sizeof运算符,而strlenC...
  • java 面试题 总结

    2009-09-16 08:45:34
    内存处理编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的...
  • 长度不定长,而且占有空间很大的数据类型的数据放在那内存的那个段里面呢?这样的数据放在 堆内存里面的。栈内存可以直接存取的,而堆内存不可以直接存取的内存。对于我们的对象来 数就是一种大的数据类型而且...
  • 答:Class可以被实例化,属于引用类型,分配在内存的堆上的,Struct属于值类型,分配在内存的栈上的. [Page] 26.根据委托(delegate)的知识,请完成以下用户控件中代码片段的填写: namespace test { public ...
  • 操作系统精髓与设计原理答案

    热门讨论 2011-11-19 15:15:08
    第二种方案中,内存的字长必须加倍,以便能发送/接受32位数量。 1.6、考虑一个计算机系统,它包含一个I/O模块,用控制一台简单的键盘/打印机电传打字设备。CPU中包含下列寄存器,这些寄存器直接连接到系统总线上...
  • (15) 在软件生命周期中,能准确地确定软件系统必须做什么和必须具备哪些功能阶段(D) 注:即第一个阶段 A. 概要设计 B. 详细设计 C. 可行性分析 D. 需求分析 (16) 数据流图用于抽象描述一个软件逻辑模型,数据...
  • 存储元件——存储一位二进制信息物理元件,存储器中最小存储单位,又叫存储基元或存储元,不能单独存取; 存储字——一个存储单元所存二进制代码逻辑单位; 存储字长——一个存储单元所存二进制代码位数;...
  • 会计理论考试题

    2012-03-07 21:04:40
    5.声音与视频信息在计算机内是以 ___D___ 表示。 A、模拟信息 B、模拟信息或数字信息 C、数字形式D、二进制形式数字 6.在Windows98中,要恢复回收站中文件,只要___B____。 A、双击该文件 B、用鼠标把该文件施...
  • loadrunner测试资料

    2010-03-21 16:51:02
     二、CPU的使用率不断上升,内存的使用率也不断上升,其他一切都很正常;  表明系统中可能产生资源争用情况;  引起原因:  开发人员注意资源调配问题。  三、 所有的事务响应时间、cpu等都很正常,业务出现...
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    在Linux 和Unix系统上,所有文件都作为一个大型树(/根)一部分访问。要访问CD-ROM上文件,需要将CD-ROM设备挂装在文件树中某个挂装点。如果发行版安装了自动挂装包,那么这个步骤可自动进行。在Linux...
  • Linux 一个 Intel 系列 CPU(CYRIX,AMD CPU也可以)硬件平台,完全免费 UNIX 兼容系统,完全适用于个人 PC。它本身就是一个完整 32 位多用户多任务操作 系统,因此不需要先安装 DOS 或其他操作...

空空如也

空空如也

1 2 3
收藏数 41
精华内容 16
关键字:

内存的存取是以什么为单位