精华内容
下载资源
问答
  • 边界对齐存储
    2021-10-06 16:56:11
    1. 结构体或类内数据元素长度都小于机器字长, 对齐单元 = 最长的数据元素长度。

    2. 结构体或类内数据元素长度存在大于机器字长的数据元素, 对齐单元 = 机器字长。

    在64位计算机中,最长的数据元素为8个字节,对齐单元 = 最长的数据元素长度,数据项仅仅能存储在地址是数据项大小的整数倍的内存位置上。例如:

    long long 占8字节,只能放在首地址为0,8,16等位置
    int 占4字节,只能放在首地址为0,4,8等位置
    char 占1字节,能放在任意位置
    在32位中,若存在long long,则 > 机器字长,对齐单元 = 机器字长=4,所以 long long有可能在4的倍数的地址上。

    更多相关内容
  • 数据边界对齐储存

    千次阅读 多人点赞 2021-04-01 03:24:57
    数据对齐储存实际就是让数据地址按照其数据类型大小的整数倍进行储存,目的在于使得数据能以最少的次数连续读取。 假如32位的系统读取数据时一个字是32位或者4个字节,当数据储存时,会尽量按照数据类型大小的整数倍...

    数据对齐储存实际就是让数据地址按照其数据类型大小的整数倍进行储存,目的在于使得数据能以最少的次数连续读取。

    假如32位的系统读取数据时一个字是32位或者4个字节,当数据储存时,会尽量按照数据类型大小的整数倍进行地址分配。

    比如数据中:

    int为4个字节;
    long long是8个字节;
    char为1个字节。

    那么在内存地址分配上:

    int只能放在首地址为0,4,8的位置上;
    long long放在首地址为0,8,16的位置上;
    char可以放在任意位置上。

    当计算机进行读操作时,对于int类型数据只需要一个周期,long long两个周期。

    但如果按照自然顺序存放,int类型就可能需要两个周期,此时的int类型数据横跨了两个字的储存空间,相当于一个仓库里有若干房间(字),每个房间里有4个按顺序编号(地址)的箱子箱子(字节),每进一次房间相当于一个周期。

    而代表int类型数据的物体需要用4个箱子,那么此时取出该物体时就需要去两个房间分别去取。

    当对齐储存时,就尽可能让某类型的数据尽可能放进一间房间,从而用最少的次数进行存取。

    但于此同时,由于为了尽量让某类型数据尽可能放进一间房间,就会有有些房间里出现空箱子,也就是两数据之间存在空地址,无法很好地利用相应空间。

    因此,可以将数据的边界对齐储存看作用空间换取时间的策略,也就是降低主存空间的实际利用率来换取存储的高效率,

    展开全文
  • 详解边界对齐

    千次阅读 多人点赞 2020-03-31 16:39:41
    按照我们之前的理解 结构数组的第二成员(下标为1)的起初存储位置是0x0014(十进制20),结构体内的double的起始存储位置是0x001C(十进制28),28不能被8整除,与double的边界对齐要求规则冲突。 所以,所有结构...

    并没有按照原文逐字逐句翻译,按照我的理解重新组织了文章。水平有限,如有错误还请指正。

    Structure Member Alignment, Padding and Data Packing

    原文链接

    引例:写出下面这个程序的运行结果

    #include <stdio.h> 
      
    // Alignment requirements 
    // (typical 32 bit machine) 
      
    // char         1 byte 
    // short int    2 bytes 
    // int          4 bytes 
    // double       8 bytes 
      
    // structure A 
    typedef struct structa_tag 
    { 
       char        c; 
       short int   s; 
    } structa_t; 
      
    // structure B 
    typedef struct structb_tag 
    { 
       short int   s; 
       char        c; 
       int         i; 
    } structb_t; 
      
    // structure C 
    typedef struct structc_tag 
    { 
       char        c; 
       double      d; 
       int         s; 
    } structc_t; 
      
    // structure D 
    typedef struct structd_tag 
    { 
       double      d; 
       int         s; 
       char        c; 
    } structd_t; 
      
    int main() 
    { 
       printf("sizeof(structa_t) = %d\n", sizeof(structa_t)); 
       printf("sizeof(structb_t) = %d\n", sizeof(structb_t)); 
       printf("sizeof(structc_t) = %d\n", sizeof(structc_t)); 
       printf("sizeof(structd_t) = %d\n", sizeof(structd_t)); 
      
       return 0; 
    } 
    

    在公布答案之前,让我们来深入研究一下其中的原理。

    数据对齐 Data Alignment

    c/c++的数据类型要求边界对齐(实际上这是由存储器的结构)决定的,并不是语言本身的特性)。
    在这里插入图片描述
    处理器的数据线的根数决定了处理器的处理字长。
    如上图左侧所示,内存是按字节为单位编址并按顺序排列,如果内存按照“一个存储体,每个单元的宽度”为一个字节”的方式来组织的话,处理器需要4个总线周期来读取一个4字节数据。

    但实际上,并没有必要花4个总线周期来读取,我们有办法让处理器用1个总线周期完成读取——采用低位多体交叉存储结构(如上图右侧所示)。

    尽管我们把内存空间分成了4个部分,但寻址的时候是仍然是把内存空间当成上图左侧那样连续的空间。

    如果把双字数据的最低的8位放在Bank 0的X地址(X是一个能被16整除的偶地址)

    X+3X+2X+1X

    多体交叉存储器需要CPU的4根地址线作为片选线来选择对应的存储体,通常会挪用低4位的地址线,低4位默认为0

    如果一个int类型的数据的起始存储位置能够被4整除,处理器在一个总线周期就能够读取完整个int。

    然而,如果一个int的起始存储位置的地址不能被4整除,如下图
    在这里插入图片描述
    处理器读取时,就需要扫描两行,需要2个总线周期完成。

    不同数据类型的边界对齐要求

    short ( 2 bytes )int ( 4 bytes )double ( 8 btyes )
    存储在Bank 0和Bank 1占用存储体一行的空间,从低位到高位,依次存放在Bank 0,Bank 1,Bank 2,Bank 332位机器:占用存储体两行的空间。需要两个总线周期来读取。
    存储在Bank 2和Bank 364位机器:存储体分成8个部分,一次能够处理64位数据,只需要1个总线周期。

    程序结果分析

    方便起见,假设每个结构体的起始地址是0x0000

    结构A

    // structure A 
    typedef struct structa_tag 
    { 
       char        c; 
       short int   s; 
    } structa_t; 
    
    • 第1个成员char占用1个字节
    • 第2个成员short占用2个字节

    如果按照下图方式存储
    在这里插入图片描述
    那么short就从奇地址开始存储,此时short就是一个非规则字
    实际上,编译器会在char和short之间插入一个空白的字节
    在这里插入图片描述
    以此来确保short的起始位置能够被2整除。
    综上所述:结构体A的大小 = sizeof(char) + 1(插入空白字节) + sizeof(short) = 4字节

    结构B

    // structure B 
    typedef struct structb_tag 
    { 
       short int   s; 
       char        c; 
       int         i; 
    } structb_t;
    
    • 第1个成员short占用2个字节
    • 第2个成员char占用1个字节
    • 第3个成员int占用4个字节

    这里需要注意的是,short和int之间char并没有对齐要求
    在这里插入图片描述

    结构C

    // structure C 
    typedef struct structc_tag 
    { 
       char        c; 
       double      d; 
       int         s; 
    } structc_t; 
    

    按照上面的分析,
    在这里插入图片描述
    这个结构的大小应该是 sizeof(char) + 7 + sizeof(double) + sizeof(int) = 1 +7 + 8 + 4 = 20

    然而,正确答案是24

    译者注:
    2013/05/01作者更新称,发现某些处理器会给结构C分配16字节的空间,作者在AMD Athlon X2处理器,GCC 4.7环境下运行得到结果是24。结构体的大小很大程度上取决于内存空间的组织方式,这是硬件层面的问题。

    为了更好的解释这个问题,下面定义一个新的结构数组

    structc_t structc_array[3];
    

    按照我们之前的理解
    在这里插入图片描述
    结构数组的第二成员(下标为1)的起初存储位置是0x0014(十进制20),结构体内的double的起始存储位置是0x001C(十进制28),28不能被8整除,与double的边界对齐要求规则冲突。

    所以,所有结构的起始存储位置必须是结构中对边界要求最严格的数据类型所要求的位置。

    综上,结构C的图解如下所示
    在这里插入图片描述

    结构D

    // structure D 
    typedef struct structd_tag 
    { 
       double      d; 
       int         s; 
       char        c; 
    } structd_t; 
    

    在这里插入图片描述
    此时结构体的大小从24变为16。

    读到这,相信你已经有所领悟,如果不是出于可读性和可维护性的原因,程序员根据结构体成员各自的边界对结构体进行排列,以减少因为边界对齐而损失的内存空间。

    malloc

    对于要求边界对齐的机器,malloc函数所返回的内存的起始位置将始终能够满足对边界对齐要求最严格的类型的要求——《c和指针》

    Q&A

    Q:堆栈当中也有边界对齐的要求吗?
    A:有。堆栈一样是在内存当中,SS中存储的堆栈段基地址就是对齐好的。举例来说,一个32位字长的处理器,SS和SP得到的堆栈位置能够被4整除。一般来说,处理器并不会去检查堆栈的边界,这是程序员的责任去确保堆栈的边界已经对齐。

    Q:如果char并没有放在Bank 0,它就会被错误的地址线读取。处理器是怎么解决有关char类型的读取问题的?
    A:通常,处理器会识别结构中的数据类型(例如ARM处理器的LDRB)。根据类型在内存中的存储情况,处理器将用最不重要的数据线来读取他

    Q:当参数在堆栈中传递时,它们还需要对齐吗?
    A:需要。例如,如果一个16位的值压入了32位宽的堆栈,这个值将自动填0来和32对齐。考虑下面这段代码

    
    void argument_alignment_check( char c1, char c2 ) 
    { 
       // Considering downward stack 
       // (on upward stack the output will be negative) 
       printf("Displacement %d\n", (int)&c2 - (int)&c1); 
    }
    

    在32位机器上运行,结果是4。

    Q:假如我非要读取一个没有对齐的数据会发生什么事?
    A:这取决于处理器。有些处理器会用几个总线周期来读取,并按照正确的方式来组合DB上传来的数据。有些处理器并没有最后两条地址线,则意味着他们无法访问奇地址(二进制数的奇偶在于最后一位是否为1),这样读取来的数据是不完整的。

    附加练习

    	struct {
    		int a;
    		short b;
    		int c;
    		char d;
    	}A;
    
    	struct {
    		double a;
    		short b;
    		int c;
    		char d;
    	}B;
    

    在32位机器上用GCC编译以上代码,求sizeof(A)和sizeof(B)
    答案:16和24

    结构B图解
    在这里插入图片描述
    下文部分内容来自《C和指针》一书
    为什么char的后面会有这么多空白的地方?用我们之前结构数组的分析思路,假如后面紧接着一个相同的结构,那么他的起始存储位置需满足结构中对边界要求最严格的的数据类型要求的位置,也就是double。而系统禁止编译器在一个结构的起始位置跳过几个字节来满足边界对齐要求。所以空出来的字节也要包括在结构体当中。

    总结

    分析结构体的大小时,按照顺序,按照“字起始地址能被占用空间的大小整除”的原则为成员分配空间,不满足原则就插入空白字节。结尾的时候要注意,按照结构数组的分析思路,看是否需要在末尾继续插入空白字节。

    展开全文
  • 系列文章目录这个学期我们进行学习了... 请使较为简单的代码确定你机器的存储模式是大端模式还是小端模式(默认使用C语言)三、关于边界对齐总结前言我以前写了这么多的代码,学到这里,才发现原来在内存中还有大...

    系列文章目录

    这个学期我们进行学习了计算机组成原理的课程,我认为该课程十分的有趣。该文章将是计算机组成原理系列的第一篇文章!

    文章目录

    系列文章目录

    前言

    一、.c文件到可执行.exe文件经历了什么?

    二、2,定义 int a=0x12345678; 请使较为简单的代码确定你机器的存储模式是大端模式还是小端模式(默认使用C语言)

    三、关于边界对齐

    总结

    前言

    我以前写了这么多的代码,学到这里,才发现原来在内存中还有大小端与边界对齐这些奇妙的东西。我们来了解下它吧。

    提示:以下是本篇文章正文内容,下面案例可供参考

    一、.c文件到可执行.exe文件经历了什么?

    使用gcc编译系统分步翻译.c文件。依次得到预处理器的输出hello.i,编译器输出hello.s,汇编器输出hello.o,链接器输出hello.exe。其中,hello.i 和 hello.s 为文本格式,hello.o 和 hello.exe为二进制格式。

    .i文件本质上还是高级语言源程序,.c预处理到.i文件,会对源程序中以#号开头的预编译命令进行处理,如果是#include,那么会将#include后面的文件内容嵌入到源程序中,生成信息量更大的.i文件。

    .s文件是由汇编语言描述的。在.s文件中可以找到与hello.c 下功能上相对应代码段。

    .o文件是.s文件上的汇编语言转换成的二进制序列。

    .exe 是在.o文件上进行链接,将多个可重定位的文件和标准库函数合并,生成一个可执行的目标文件。

    二、2,定义 int a=0x12345678; 请使较为简单的代码确定你机器的存储模式是大端模式还是小端模式(默认使用C语言)

    答:使用的代码如下:

    int a=0x12345678;

    printf(“%x”,a);

    最终打印输出12345678,所以是用小端模式存储的。

    三、关于边界对齐

    3,定义结构体如下:

    1.  struct stest{

    2.      int a;

    3.      short b;

    4.      double c;

    5.      char d;

    6.      short e;

    7.  }test;

    8.

    9.  test.a = 0x12345678;

    10. test.b = 0xabcd;

    11. test.c = 1.0;

    12. test.d = 0x09;

    13. test.e = 0xeeff;

    试回答:

    (1) test结构体变量在机器内存中共占用多少个字节?为什么?

    答:占用20个字节,在x86中,为了加快取数操作,用到了端对齐,所以使得原本只需17个字节就可以存储的数据,却使用了20个字节。

    (2) 用printf函数展示test各成员变量在内存中的位置和大小分布。

    答:程序和运行结果如下:

    688ea185315d9541e256f65ba2796c31.png

    0dd4799795846b5dc0dbe01bae93e58d.png

    (3)使用#pragma pack(n) 指定数据对齐方式(这里,n分别取1, 2, 4, 8),将(1)、(2)涉及的问题重新回答一遍,总结规律。

    答:实际上数据的存储不是顺序存储的,有时候为了对齐需要补齐空字节。

    总结

    对计算机对.c文件编译进行了简单的分析和对大小端与边界对齐进行了试验。

    展开全文
  • 对于 C 语言中的边界对齐存储,要求如下,即对于存放某长度为 m 字节的数据,存放首地址需为m 字节的整数倍,同时,结构体整体的大小是最大成员长度的整数倍。 对于地址0xC00D,D 转换成十进制为 13,不整除 c(2 ...
  • 【408 考研真题】大小端 & 边界对齐存储

    千次阅读 多人点赞 2019-04-08 05:49:32
    文章目录一道 408 考研真题顺序存储的方式:大端法和小端法C 语言中的边界对齐存储参考资料 一道 408 考研真题 【答案】D 【解析】 从答案可以看出,先要将 273 转换成 16 进制。a = 273 = 0x00000111。其中,1 位...
  • 结构的存储分配——边界对齐

    千次阅读 2019-06-30 19:46:42
    2,结构的起始存储位置为该结构中边界对齐要求最严格的数据类型所要求的位置 3,第一个成员存放在偏移量为0的位置 接下来的各成员存放在偏移量为该成员的类型所占字节数的整数倍的位置 特别地,当成员为结构时,该...
  • C-边界对齐

    2020-12-24 11:45:06
    转自:http://blog.csdn.net/b_h_l/article/details/7738197许 多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据...当一种类型S的对齐模数与另一种类型T的对齐模数的比值是大于1的整数...
  • 【考研真题】边界对齐存储

    万次阅读 多人点赞 2018-09-28 15:13:46
    某计算机存储器按字节编址,采用小端方式存放数据,假定编译器规定int和short型长度分别为32位和16位,并且数据按边界对齐存储,其C语言程序段如下: struct{ int a; char b; short c; }record; record.a=273; ...
  • 标题:结构的存储分配结构,对于其列表中的成员,在内存分配时,要求边界对齐。也就是说,如果某个机器的整型值长度为四个字节,并且它的内存地址必须能够被4整除,那么它在内存中存放状态就是有条件的,它不能任意...
  • 展开全部如果声明的变量的常规对齐边界小于n,__align(n)是非常有用的。32313133353236313431303231363533e78988e69d8331333433663039八字节对齐方式可以显著提高 VFP 指令的性能。可以将__align与extern 和static ...
  • 边界对齐

    千次阅读 多人点赞 2019-08-09 19:06:35
    一、什么是内存对齐 先来看一个结构: typedef struct _tagMem_Align { char c1; short s; char c2;...假设没有边界对齐,即内存是紧凑排列的,那么假设c1的地址是0,那么s的地址就是1,c...
  • 一、首先,为什么要进行内存对齐,即在内存中为什么要这么存放数据呢??? 原因一:在内存中存放数据是为了给CPU使用,但是CPU从内存中读取数据并非是一个字节一个字节进行读取的,而是一块一块进行读取的,块的...
  • 数据在计算机存储器中以边界对齐存储方式是很常用的。本文将以理论和C语言程序实际结合,展示计算机中存储器的奥秘。
  • 计算机组成原理——C语言中的边界对齐问题

    千次阅读 多人点赞 2019-05-29 21:07:20
    边界对齐 例如一个存储字长为32位的机器,现来详述一下依次存入一个int,short,double,char,short类型的数据的过程。假定int ,short,double ,char分别为4,2,8,1字节。那么它们分别占据字、半字、双字、字节。 字...
  • 本文详细讲述了C语言程序设计中内存对其的概念与用法。分享给大家供大家参考之用。具体如下:一、字节对齐基本概念现代计算机中内存空间都是按照byte划分的,从理论上讲... 对齐的作用和原因:各个硬件平台对存储空...
  • 数据对齐存储

    千次阅读 2020-02-18 17:05:41
    计算机里面内存的数据存储结构以及为什么要边界对齐 行边界存储 结构的存储分配规则: 数据的大小端问题 参考文献 计算机里面内存的数据存储结构以及为什么要边界对齐 计算机里面的从主存的是有一个个基本的...
  • 结构体边界对齐问题

    2019-11-19 11:35:32
    结构体边界对齐问题 在构造DNS应答包的Answer字段时,我定义了一个结构体,如下所示: typedef struct{ __u16 name; __u16 type; __u16 class; __u32 ttl; __u16 length; __u32 ipv4_addr; }DNS_ANSWER_DATA; ...
  • 欢计算机组成原理 第二章——结构体中成员变量按数据边界对齐存储的规则 结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则: 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; ...
  • c中结构体边界对齐(转)2011-11-23 11:15:52|分类: C&C++ |标签: |字号大中小C语言结构体对齐也是老生常谈的话题了。基本上是面试题的必考题。结构体到底怎样对齐?下面总结了对齐原则,在没有#pragma pack宏的...
  • 所以,在64位中,最长的数据元素为8个字节,对齐单元 = 最长的数据元素长度,数据项仅仅能存储在地址是数据项大小的整数倍的内存位置上。例如: long long 占8字节,只能放在首地址为0,8,16等位置 int 占4字节,...
  • 文章目录大小端模式边界对齐 大小端模式 大家一定知道:多字节数据在内存里一定是占连续的几个字节 最高有效字节我们用MSB表示 最低有效字节我们用LSB表示 例如 大端模式更便于人类阅读 小端模式更便于便于...
  • 字节对齐与边界对齐

    千次阅读 2016-12-25 11:33:44
    每个硬件平台对于存储空间的处理不同。有没有字节对齐主要是对于存取效率的影响。 ü  对于协议栈开发,上下层对于字节对齐的处理不同,将直接影响数据的读取。 Ubuntu 2.6.32内核,gcc版本为4.7.0 l  ...
  • 结构体边界对齐

    2018-05-30 13:02:30
    许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。...
  • C语言结构中的边界对齐问题

    千次阅读 多人点赞 2017-02-14 23:56:56
    没错,今天2月14,单身狗如我情人节也只能苦逼地撸代码了。不知道大家有没有发现一个奇怪的现象,见图~ ... 事实上,结构成员在内存中的存储并不是想当然地一个紧挨着一个排列下来的,由于提高数据读取速度的要求以及
  • union是共享存储单元的数据结构,它所占用的内存长度等于最长的成员的内存长度。 struct的大小取决于它所以的成员的内存长度之和(理论上是这样... 假设系统为x分配的地址为0x80100000(以边界对齐存储int4B大小,...
  • 边界对齐的作用思考

    千次阅读 2018-11-23 14:20:49
    边界对齐应用在存储中,如结构体的存储,因为结构体中存在不同的数据类型,通过边界对齐可以使存储效率提升。 (2016.18)某计算机主存空间是4GB,字长是32位,按照字节编址。采用32位定长指令格式,若指令按照字...
  • 法则:莫类型数据边界对齐存储的起始地址是该数据类型字长的整数倍 即如果是双子长(16bit)那么边界对齐的起始地址的末3位必须是000 这就保证了添加该数据进去以后依然是存储是整数倍 所以我解释一下s1的内存...
  • 边界对齐问题

    万次阅读 2012-06-28 16:18:50
    结构体边界对齐   许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的...
  • 【C语言】字节对齐和边界对齐

    千次阅读 2017-04-21 00:39:12
    一、什么是字节对齐   现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以...   各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,837
精华内容 13,534
关键字:

边界对齐方式存储