精华内容
下载资源
问答
  • 数据边界对齐储存 千次阅读 多人点赞
    2021-04-01 03:24:57

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

    假如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个箱子,那么此时取出该物体时就需要去两个房间分别去取。

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

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

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

    更多相关内容
  • 数据在计算机存储器中以边界对齐存储的方式是很常用的。本文将以理论和C语言程序实际结合,展示计算机中存储器的奥秘。

    前言:在计算机组成原理中,数据在存储器中以边界对齐存储的方式是很常用的。

    教材参考:计算机组成原理(第2版) (唐朔飞著) P306

    思考:下面来看两段代码(32位C语言环境),你能说出运行的结果吗?

    // 代码段1
    # include <stdio.h>
    typedef struct test
    {
    	char a;
    	char b;
    	short c;
    	int d;
    }t;
    int main(){
    	t *x;
    	printf("%d",sizeof(*x));
    }
    
    // 代码段2
    #include <stdio.h>
    typedef struct test
    {
    	char a;
    	short b;
    	char c;
    	int d;
    }t;
    int main(){
    	t *x;
    	printf("%d",sizeof(*x));
    }
    

    答案:结果分别是:8 、12

    可以看到,代码段的不同之处在于结构体第2、3个位置分别放的是char,short和short,char,存放顺序的不同为什么会导致结构体的大小不一样呢?这就是边界对齐存储在计算机中的应用。

    32位计算机按字编址,1字应为4B。因此按照边界对齐存储规则:半字地址是2整数倍,字地址是4整数倍,双字地址是8整数倍。

    相应地,64位计算机按字编址,1字应为8B。因此按照边界对齐存储规则:半字地址是4整数倍,字地址是8整数倍,双字地址是16整数倍。

    以此类推。

    下面来看下结构体构成:char (1B)、short(2B)、int(4B)。则32位下,半字地址(short)要为2整数倍,字地址(int)要为4整数倍。

    ① 按第一个代码段来存储,char->char->short->int
    分别是1B ( a ) -> 1B ( b ) -> 2B ( c ) -> 4B ( d ):

    0x000x010x020x03
    abcc
    0x040x050x060x07
    dddd

    刚好存满,不需要边界对齐,占用8个存储单元。

    ② 按第二个代码段来存储,char->short->char->int
    分别是1B ( a ) -> 2B ( b ) -> 1B ( c ) -> 4B ( d ):

    0x000x010x020x03
    a-bb
    0x040x050x060x07
    c---
    0x080x090x0a0x0b
    dddd

    可以看到,由于半字地址(short)在0x01不是2的整数倍,往后移进行对齐;由于字地址(int)在0x05不是4的整数倍,往后移进行对齐,所以占用了12个存储单元。

    下面再来看一段代码。

    // 代码段3
    #include <stdio.h>
    typedef struct test
    {
    	char a;
    	short b;
    	int d;
    	char c;
    }t;
    int main(){
    	t *x;
    	printf("%d",sizeof(*x));
    }
    

    输出结果:12

    对应的存储结构 char->short->int->char
    1B ( a ) -> 2B ( b ) -> 4B ( c ) -> 1B ( d ):

    0x000x010x020x03
    a-bb
    0x040x050x060x07
    cccc
    0x080x090x0a0x0b
    d---

    这个结果可以说明,结构体整体长度是字(32位下1字为4B)的整数倍,尽管0x09-0x0b没有存储内容,但会填写空白进行补齐。

    到这里,相信你已经理解了边界对齐的方式,下面来看看拓展的内容。


    提示:以下内容是在真实的x64计算机中测试,结论并不适用于考研或其他应试类题目

    实际上,无论使用x86(32位)还是x64(64位)的C编译器,默认采用下面的这种对齐方式。

    结构体里面有64bit的类型那么就使用8字节对齐方式,如果最大的是32bit类型就使用4字节对齐方式,以此类推。而且当struct里面包含struct或者union的时候,被包含的struct或者union的最大基础类长度会传递给上层的struct。

    验证一:边界对齐的位数 等于 结构体内字长最大数据类型的位数

    ① 下列结构体最长是short,按2B(16位)对齐。

    #include <stdio.h>
    typedef struct test
    {
    	short a;   // 2B
    	short b;   // 2B
    	short c;   // 2B
    }t;
    int main() {
    	t *x;
    	printf("%d", sizeof(*x));
    }
    

    上述代码在x86环境运行,输出结果是6(理论上按16位是6,按32位是8),说明这个结构体按16位进行边界对齐。

    ② 下列结构体最长是int,按4B(32位)对齐。

    #include <stdio.h>
    typedef struct test
    {
    	int a;  // 4B
    	char b; // 1B
    	int c;  // 4B
    }t;
    int main() {
    	t *x;
    	printf("%d", sizeof(*x));
    }
    

    上述代码在x86和x64环境运行,输出结果都是12(理论上按32位是12,按64位是16),说明这个结构体按32位进行边界对齐。

    ③ 下列结构体最长是double,按8B(64位)对齐。

    #include <stdio.h>
    typedef struct test
    {
    	double a;  // 8B
    	char b;    // 1B
    }t;
    int main() {
    	t *x;
    	printf("%d", sizeof(*x));
    }
    

    上述代码在x86和x64环境运行,输出结果都是16(理论上按32位是12,按64位是16),说明这个结构体按64位进行边界对齐。

    这可能是为了更高效的利用存储空间而采用的一种折中办法(字是变长的)。在计算机组成原理的很多设计方法中都有体现,例如Cache中的组相联映射便是直接映射全相联映射的一种折中。

    验证二:同一个C程序中,不同结构体可以按不同位长进行边界对齐:

    #include <stdio.h>
    typedef struct test1   // 32:20  64:24
    {
    	double a;
    	char b;
    	int c;
    	char d;
    }t1;
    typedef struct test2   // 32:12  64:16
    {
    	int a;
    	int b;
    	int c;
    }t2;
    int main() {
    	t1 *x;
    	t2 *y;
    	printf("%d\n", sizeof(*x));
    	printf("%d", sizeof(*y));
    }
    

    上面的注释标明了按32和64位进行对齐理论应该得到的数据,而结果是24和12,说明分别是按64位和32位对齐。

    下面补充32位机和64位机的数据字长:
    32位 vs 64位
    那么我们最终可以得出结论:我们现在所用的64位计算机当然是64位的,只不过为了提高效率,在某些程序片段中会以32位的特性运行。当然,如果你只是为了学习理论,只需要掌握理论的情况即可,不必对现实过多考虑。

    最后,感谢你能看到这里,祝大家学业有成,成功上岸。

    作者个人博客:515code.com

    写于 2021/08/24 凌晨

    展开全文
  • 欢计算机组成原理 第二章——结构体中成员变量按数据边界对齐存储的规则 结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则: 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; ...

    结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则:

    1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

    2) 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);

    3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍**(如成员变量中最宽的为int为32位,4B,则结构体大小应该为4B的整数倍)**,如有需要编译器会在最末一个成员之后加上填充字节{trailing padding}。

    对于以上规则的说明如下:

    第一条:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。

    第二条:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员大小的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。

    第三条:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。

    如下题所示:
    p48 第3题
    解1:

    1. 0xC00D相对于结构体首地址的偏移量为 D - 8 = 5
    2. 因为按字节编址,所以一共(5 * 8) = 40bit。40/16 不能整除。
    3. 根据第二条规则,需要填充一定字节的空位。此处插入1字节(1B)的空位。此时为(6 * 8)/16 = 3,可以整除。

    解2:

    1. 0xC00D相对于结构体首地址的偏移量为 D - 8 = 5
    2. short类型长度16位,即2字节。5/2 不能整除。
    3. 根据第二条规则,需要填充一定字节的空位。此处插入1字节(1B)的空位。此时为6/2 = 3,可以整除。
      在这里插入图片描述
    展开全文
  • 展开全部如果声明的变量的常规对齐边界小于n,__align(n)是非常有用的。32313133353236313431303231363533e78988e69d8331333433663039八字节对齐方式可以显著提高 VFP 指令的性能。可以将__align与extern 和static ...

    展开全部

    如果声明的变量的常规对齐边界小于 n,__align(n) 是非常有用的。32313133353236313431303231363533e78988e69d8331333433663039八字节对齐方式可以显著提高 VFP 指令的性能。可以将 __align 与 extern 和 static 一起使用。

    由于 __align 是存储类修饰符,因此不能将其用于:类型,包括 typedef 和结构定义、函数参数。只能进行过对齐。也就是说,可以将两个字节的对象按 4 个字节对齐,而不能将 4 个字节的对象按两个字节对齐。

    扩展资料

    对齐的作用和原因:

    各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。

    其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)。

    如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。显然在读取效率上下降很多。

    展开全文
  • 大小端 & 边界对齐存储

    千次阅读 2021-06-16 14:05:46
    因为题目给出数据按边界对齐存储。对于 C 语言中的边界对齐存储,要求如下,即对于存放某长度为 m 字节的数据,存放首地址需为m 字节的整数倍,同时,结构体整体的大小是最大成员长度的整数倍。 对于地址0xC00D,D ...
  • 边界对齐存储

    2021-10-06 16:56:11
    在64位计算机中,最长的数据元素为8个字节,对齐单元 = 最长的数据元素长度,数据项仅仅能存储在地址是数据项大小的整数倍的内存位置上。例如: long long 占8字节,只能放在首地址为0,8,16等位置 int 占4字节,只能...
  • 数据对齐存储

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

    万次阅读 多人点赞 2018-09-28 15:13:46
    某计算机存储器字节编址,采用小端方式存放数据,假定编译器规定int和short型长度分别为32位和16位,并且数据按边界对齐存储,其C语言程序段如下: struct{ int a; char b; short c; }record; record.a=273; ...
  • 计算机数据存储边界对齐的方式,存储字长,存储单元的概念
  • 详解边界对齐

    千次阅读 多人点赞 2020-03-31 16:39:41
    数据对齐 Data Alignment c/c++的数据类型要求边界对齐(实际上这是存储器的结构决定的,并不是语言本身的特性)。处理器的数据线的根数决定了处理器的处理字长。 如上图左侧所示,内存是字节寻址并顺序排列,...
  • C-边界对齐

    2020-12-24 11:45:06
    多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对 齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。...
  • 【408 考研真题】大小端 & 边界对齐存储

    千次阅读 多人点赞 2019-04-08 05:49:32
    文章目录一道 408 考研真题顺序存储的方式:大端法和小端法C 语言中的边界对齐存储参考资料 一道 408 考研真题 【答案】D 【解析】 从答案可以看出,先要将 273 转换成 16 进制。a = 273 = 0x00000111。其中,1 位...
  • 数据结构内存边界对齐的三条原则
  • 目录数据存储顺序边界对齐测试程序 数据存储顺序 (1)大端存储:将一个字的高的有效字节放在内存的低地址端,低有效字节放在内存的高地址端。 (2)小端存储:将一个字的低的有效字节放在内存的低地址端,高有效字节...
  • 结构的存储分配——边界对齐

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

    2022-04-18 22:34:04
    按边界对齐,可使读写数据位于8i~8i+7(i=0,1,2,…) 单元 指令系统支持对字节、半字、字及双字的运算 各种不同长度的数据存放时,有两种处理方式: – 按边界对齐(若一个字为32位) • 字地址:4的倍数(低两位为
  • 所以,在64位中,最长的数据元素为8个字节,对齐单元 = 最长的数据元素长度,数据项仅仅能存储在地址是数据项大小的整数倍的内存位置上。例如: long long 占8字节,只能放在首地址为0,8,16等位置 int 占4字节,...
  • 文章目录大小端模式边界对齐 大小端模式 大家一定知道:多字节数据在内存里一定是占连续的几个字节 最高有效字节我们用MSB表示 最低有效字节我们用LSB表示 例如 大端模式更便于人类阅读 小端模式更便于便于...
  • 计算机组成原理——C语言中的边界对齐问题

    千次阅读 多人点赞 2019-05-29 21:07:20
    边界对齐 例如一个存储字长为32位的机器,现来详述一下依次存入一个int,short,double,char,short类型的数据的过程。假定int ,short,double ,char分别为4,2,8,1字节。那么它们分别占据字、半字、双字、字节。 字...
  • 首先,在没有#pragma pack的情况下,要遵循如下几个原则:原则1、普通数据成员对齐规则:第一个数据成员放在offset为0的地方(可假设起始位置为0,事实上,结构体成员要从其内部最大元素大小的整数倍地址处开始存储)...
  • 一、首先,为什么要进行内存对齐,即在内存中为什么要这么存放数据呢??? 原因一:在内存中存放数据是为了给CPU使用,但是CPU从内存中读取数据并非是一个字节一个字节进行读取的,而是一块一块进行读取的,块的...
  • 标题:结构的存储分配结构,对于其列表中的成员,在内存分配时,要求边界对齐。也就是说,如果某个机器的整型值长度为四个字节,并且它的内存地址必须能够被4整除,那么它在内存中存放状态就是有条件的,它不能任意...
  • union是共享存储单元的数据结构,它所占用的内存长度等于最长的成员的内存长度。 struct的大小取决于它所以的成员的内存长度之和(理论上是这样... 假设系统为x分配的地址为0x80100000(以边界对齐存储int4B大小,...
  • 系列文章目录这个学期我们进行学习了... 请使较为简单的代码确定你机器的存储模式是大端模式还是小端模式(默认使用C语言)三、关于边界对齐总结前言我以前写了这么多的代码,学到这里,才发现原来在内存中还有大...
  • 边界对齐的作用思考

    千次阅读 2018-11-23 14:20:49
    边界对齐应用在存储中,如结构体的存储,因为结构体中存在不同的数据类型,通过边界对齐可以使存储效率提升。 (2016.18)某计算机主存空间是4GB,字长是32位,按照字节编址。采用32位定长指令格式,若指令按照字...
  • c中结构体边界对齐(转)2011-11-23 11:15:52|分类: C&C++ |标签: |字号大中小C语言结构体对齐也是老生常谈的话题了。基本上是面试题的必考题。结构体到底怎样对齐?下面总结了对齐原则,在没有#pragma pack宏的...
  • 字节对齐与边界对齐

    千次阅读 2016-12-25 11:33:44
    对于协议栈开发,上下层对于字节对齐的处理不同,将直接影响数据的读取。 Ubuntu 2.6.32内核,gcc版本为4.7.0 l  字节对齐:__attribute__((packed))与#pragma pack(n) #pragma pack() 取消当前设
  • 其实诸如:对于char型数据,其自身对齐值为1,对于short型为2,对于int、float、double类型,其自身对齐值为4,这些已有类型的自身对齐值也是基于数组考虑的,只 是因为这些类型的长度已知了,所以他们的自身对齐...
  • 实验一 大小端与边界对齐 1,编写hello.c程序,使用gcc编译系统分步翻译该程序。 (1)依次得到预处理器的输出hello.i,编译器输出hello.s,汇编器输出hello.o,链接器输出hello.exe;
  • C语言结构中的边界对齐问题

    千次阅读 多人点赞 2017-02-14 23:56:56
    没错,今天2月14,单身狗如我情人节也只能苦逼地撸代码了。不知道大家有没有发现一个奇怪的现象,见图~ ... 事实上,结构成员在内存中的存储并不是想当然地一个紧挨着一个排列下来的,由于提高数据读取速度的要求以及

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,749
精华内容 12,699
关键字:

数据按边界对齐存储