精华内容
下载资源
问答
  • 内存对齐方式

    2005-08-06 11:01:00
    这就涉及到内存对齐的问题了.VC++中默认的对齐方式为两个字节如下为定义为一个字节,这样内存中就不会有什么陷阱了:#pragma pack(1)typedef struct{ char RiffID[4]; DWORD dwFileDataSize; char WaveID[4]; ch

    在结构体定义的时候,如果要将结构体向文件中写入的话.需要保证结构体在内存中不能出现内存陷阱.这就涉及到内存对齐的问题了.VC++中默认的对齐方式为两个字节

    如下为定义为一个字节,这样内存中就不会有什么陷阱了:

    #pragma pack(1)

    typedef struct

    {

        char RiffID[4];

        DWORD dwFileDataSize;

       char WaveID[4];

       char FMTID[4];

       DWORD dwFmtSize;

       WORD wFomatTag;

       WORD wChannels;

       DWORD dwSamplePerSec;

       DWORD dwAvgBytesPerSec;

        WORD wBlockAlign;

       WORD wBitsPerSample;

       WORD wEmpty;

       char  DataID[4];

       DWORD dwDataSize;

    }WAVEFILEHDRULAW;

    #pragma pack()

    如果没有pragma的命令,则在内存中回在wEmpty前面出现一个WORD大小的内存陷阱,程序中是无法对次

    内存进行编辑的.但是会影响到往文件中写入的结果.这个内存陷阱也会被写入文件头.

    这样当文件头是用来表示某一种文件的.则系统会无法辨认而出错的.

    展开全文
  • 1. 内存对齐方式虽然所有的变量最后都会保存在特定地址的内存中,但相应的内存空间必须满足内存对齐的要求。主要出于两个方面的原因: (1) 平台原因: 不是所有的硬件平台(特别是嵌入式系统中使用的低端处理器)...

    1. 内存对齐方式

    虽然所有的变量最后都会保存在特定地址的内存中,但相应的内存空间必须满足内存对齐的要求。主要出于两个方面的原因:
    (1) 平台原因:
    不是所有的硬件平台(特别是嵌入式系统中使用的低端处理器)都能访问任意地址上的任意数据,某些硬件平台只能访问对齐的地址,否则会出现硬件异常。
    (2) 性能原因:
    如果数据存放在未对齐的内存空间中,则处理器访问变量时需要做两次内存访问,而对齐的内存访问仅需一次访问。

    在32位微处理器中,处理器访问内存都是按照32位进行的,即一次读取或写入都是4个字节,比如地址0x0~0xF这16字节的内存,对于微处理器来说,不是将其看做16个单一字节,而是4个块,每块4个字节。如下图
    这里写图片描述

    显然,只能从0x0、0x4、0x8、0xC等地址为4的整数倍的内存中一次取出4个字节,并不能从任意地址开始一次读取4个字节。假定将一个占用4个字节的int类型的数据存放在地址0开始的4字节内存中,其示意图如下
    这里写图片描述
    由于int类型数据存放在块0中,因此CPU仅需一次内存访问即可完成对该数据的读取或写入。反之,如果将int类型数据存放在地址1开始的4字节内存空间中,其示意图如下
    这里写图片描述
    此时,数据存放在块0和块1两个块中,若要完成对该数据的访问,必须经过两次内存访问,先访问块0得到数据的3个字节,再通过访问块1得到该数据的1个字节,最后通过运算,将这几个字节合并为一个完整的int型数据。由此可见,若数据存储在未对齐的内存空间中,将大大降低CPU的效率。但在某些特定的微处理器中,它根本不愿意干这种事情,这种情况下,就出现系统异常,直接崩溃了。

    2. 结构体的存储

    我们知道,数组是相同类型有序数据的集合,但很多时候需要将不同类型的数据捆绑在一起作为一个整体对待,使程序设计更方便。在C语言中,这样一组数据被称为结构体。其内存对齐的规则如下:
    (1) 结构体各个成员变量的内存空间的首地址必须是“对齐系数”和“变量实际长度”中较小者的整数倍。“对齐系数”是【#pragma pack指定的数值】、【未指定#pragma pack时,系统默认的对齐模数(32位系统为4字节,64位为8字节)】。假设要求变量的内存空间要求按照4字节对齐,则内存空间的首地址必须是4的整数倍,满足条件的地址为0x0, 0x4, 0x8, 0xC…
    (2) 对于结构体,在其各个数据成员都完成对齐后,结构体本身也需要对齐,即结构体占用的总大小应该为“对齐系数”和“最大数据成员长度”中较小值的整数倍。

    如下的结构体,在32位机器上编译,其成员数据的总长度为4+2+3+4+1+8 = 22(字节)

    #pragma pack(4)
    struct TEST
    {
        long a;         //4
        short b;        //2
        char c[3];      //3
        float d;        //4
        char e;         //1
        double f;       //8
    }test;
    

    有如下的测试程序

    int main(void)
    {
        short len = sizeof(test);
        printf("test length is %d.\n", len);
        return 0;
    }

    下面是输出结果,结果表明结构体占用28个字节的内存,大于22字节。
    这里写图片描述
    其实,正是由于内存对齐的原因造成了这种现象,下图是每个变量在内存的分布图,其中空白部分是内存弃用部分,这些浪费空间的前面,存放的都是char型数据,由于char型数据只占用一个字节,往往使得其紧接着的空间不能被其它长度更长的数据使用。
    这里写图片描述

    为了降低内存浪费的概率,应该在char型数据之后,存放长度较小的成员。即在定义结构体时,应该按照长度递增的顺序依次定义各个成员。优化后的实例代码为

    #pragma pack(4)
    struct TEST
    {
        char e;         //1
        char c[3];      //3
        short b;        //2
        long a;         //4
        float d;        //4
        double f;       //8
    }test;

    运行测试程序,输出结果为
    这里写图片描述
    可见,通过调整结构体的成员顺序,达到了优化内存的目的。各个成员变量在内存中的分布图为
    这里写图片描述

    结构体只浪费了2个字节的空间,内存使用率达到92%。显然通过优化结构体成员的定义顺序,在同样满足内存对齐的要求下,可以大大减小内存的浪费。

    展开全文
  • C语言中内存对齐方式

    2015-04-16 22:08:58
    内存对齐,因为它是对C/C++程序员透明的,在很多C,C++课本中也没有讲清楚,所以今天写了这篇博客,讲述为什么需要内存对齐内存对齐怎么计算·····

    内存对齐,因为它是对C/C++程序员透明的,在很多C,C++课本中也没有讲清楚,所以今天写了这篇博客,讲述为什么需要内存对齐,内存对齐怎么计算?奋斗

    为什么需要内存对齐?

    1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的。某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
    2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

    内存对齐怎么计算?

    首先,需要知道内存对齐的四个准则:

    1.第一个成员与结构体变量的偏移量为0

    2.其他变量要对齐到对齐数(对齐数取编译器预设的一个对齐整数与该成员大小的较小值)的整数倍地址

    3.结构体总大小为最大对齐数的整数倍

    接下来通过几个例子来说明问题:(在4字节的32位机上)

    #include <iostream>
    #include<stdio.h>
    using namespace std;
    
    struct Test
    {
    	int a;
    	char b;
    	short c;
    };
    
    int main(void)
    {
    	Test test;
    	printf("a=%p\n", &test.a);
    	printf("b=%p\n", &test.b);
    	printf("c=%p\n", &test.c);
    	cout << sizeof(Test) << endl;
    	return 0;
    }

    输出结果:


    分析过程:

    1、首先确定每个成员的有效对齐值,由于这里没有指定对齐值 所以 每个成员的有效对齐值就是其自身数据类型的对齐值
    a 的对齐值是 4字节(32位机上) b 的对齐值是 1字节 c 的对齐值是2字节
    2、起始地址必须满足“起始地址%N = 0”
    令起始地址位0x0000  按照变量的顺序存储 则 0x0000%4 = 0;满足条件 占用4个字节 0x0000-0x0003 折四个字节
    变量b 的起始地址 是 0x0004%1 = 0满足条件 占用一个字节 就是0x0004
    变量c 的起始地址 是 0x0005%2 !=0 所以起始地址要向后移位 知道满足条件位置 0x0006%2 = 0 满足条件 占用2字节 0x0006- 0x0007
    总共占用了8字节

    如果变换为这样:

    #include <iostream>
    #include<stdio.h>
    using namespace std;
    
    struct Test
    {
    	
    	char b;
    	int a;
    	short c;
    };
    
    int main(void)
    {
    	Test test;
    	printf("a=%p\n", &test.a);
    	printf("b=%p\n", &test.b);
    	printf("c=%p\n", &test.c);
    	cout << sizeof(Test) << endl;
    	return 0;
    }
    输出:


    分析过程:

    1、找变量的有效对齐位
     还是没有指定对齐值 所以就是变量自身的对齐值 b 1字节, a 4字节,c 2字节
    2、起始地址满足 对有效对齐值取余=0的条件
     令其实地址为0x0000 % 1 = 0满足 
    变量a 的起始地址为0x0001 %4 !=0
     则其实地址要向后移位 知道满足条件为止 0x0004%4 = 0 占用4个字节 0x0004-0x0007
    变量c 的起始地址为 0x0008 %2
     = 0 满足条件 占用两个字节 0x0008-0x0009
    总共占用了10个字节的内存空间
    3、圆整 结构体的有效对齐值是4 所以 总共占用的硬为(10+2)%4
     = 0个字节 12个字节 

    再来看以下几个例子练习下:(以下例子是在VS2013上写的,默认成员内存对齐为8)

    例子1:


    输出:16

    例子2:


    输出:24

    例子3:


    输出:16


    输出:12

    附录:微软经典面试题:

    #include <iostream.h>
    
    #pragma pack(8)
    
    struct example1
    
    {
    
    short a;
    
    long b;
    
    };
    
    struct example2
    
    {
    
    char c;
    
    example1 struct1;
    
    short e;
    
    };
    
    #pragma pack()
    
    int main(int argc, char* argv[])
    
    {
    
    example2 struct2;
    
    cout << sizeof(example1) << endl;
    
    cout << sizeof(example2) << endl;
    
    cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2) << endl;
    
    return 0;
    
    }
    输出:

    8

    16

    4

    在网络程序中,掌握这个概念可是很重要的喔,在不同平台之间(比如在Windows 和Linux之间)传递2进制流(比如结构体),那么在这两个平台间必须要定义相同的对齐方式,不然莫名其妙的出了一些错的······

    展开全文
  • C、C++中的内存对齐方式/

    示例1:

    
    using namespace std;
    
    struct Node1{
        bool m1;
        int m2;
    	bool m3;
    	double m4;
    	bool m5;
    };
    // struct Node2{
    //     char m1;
    //     char m2;
    // 	int m3;
    // };
    
    int main()
    {
    	cout << sizeof(Node1) << endl;
    /*	cout << sizeof(Node2) << endl;*/
    }</span>

    输出结果:32


    原因:double(8) > int(4) > bool(1)

    所以在double出现之前采用int,原结构体每个成员变量内存分配为:1、4、1、8、1

    故1扩展为4,4保持不变,第二个1必须扩展为8,这样1(4) + 4(4) + 1(8) = 16才能被8整除,最后一个1扩展为8.

    总共内存4+4+8+8+8 = 32.



    示例2:

    <span style="font-size:18px;">#include <iostream>
    
    using namespace std;
    
    struct Node1{
        bool m1;
    	bool m3;
        int m2;
    	double m4;
    	bool m5;
    };
    // struct Node2{
    //     char m1;
    //     char m2;
    // 	int m3;
    // };
    
    int main()
    {
    	cout << sizeof(Node1) << endl;
    /*	cout << sizeof(Node2) << endl;*/
    }</span>
    输出结果:24


    原因:参考第一条


    示例3:数组

    <span style="font-size:18px;">#include <iostream>
    
    using namespace std;
    // 
    // struct Node1{
    //     bool m1;
    // 	bool m3;
    //     int m2;
    // 	double m4;
    // 	bool m5;
    // };
    struct Node2{
        char m1;
        char m2[6];
    };
    
    
    int main()
    {
    /*	cout << sizeof(Node1) << endl;*/
    	cout << sizeof(Node2) << endl;
    }</span>

    结果:7


    原因:char数组不可看成一个对齐整体,Node2对齐基于1;故结果为7;


    示例4:结构体中的结构体

    <span style="font-size:18px;">#include <iostream>
    
    using namespace std;
    
    
    struct Node1{
        char m1;
        double m2;
    	char m3;
    };
    struct Node2{
    	char m1;
    	Node1 m2;
    };
    
    
    int main()
    {
    /*	cout << sizeof(Node1) << endl;*/
    	cout << sizeof(Node2) << endl;
    }</span>

    输出结果:32

    原因:

    Node1为24,这个参考示例1;

    但是Node1中的对齐基数是8;因为Node2中只有char m1,基数为1小于Node1的基数8;

    所以采取Node1的对齐基数8;但是Node1是一个整体,不能将其填充部分的内容分给Node2中的m1使用。故

    m1必须同样分配8字节给他,总字节数;8+24=32



    本文由Cout_Sev 搜集整理

    转载注明出处

    http://blog.csdn.net/cout_sev

    谢谢!


    展开全文
  • 结构体的对齐方式必须是程序员所了解的,关于内存对齐方式的优点和部分知识可以参阅http://www.ibm.com/developerworks/library/pa-dalign/ 结构体占用的存储空间(struct & sizeof) 概要:结构体所占用的空间只...
  • 问题解答https://www.cnblogs.com/jijiji/p/4854581.html
  • 一.背景:1.使用#pragma定义结构体:RECV_CMD_DATA_t和RECV_CMD_PACK_t,按照1字节进行内存对齐#pragma pack(1) typedef struct recv_cmd_data { int iType; long long llInt; int iLen; ...
  • C语言中内存对齐方式摘录

    千次阅读 2013-09-23 08:48:20
    原来对内存对齐一直没弄清楚,现在找到两篇网友的文章备忘: http://blog.csdn.net/arethe/article/details/2548867 http://blog.sina.com.cn/s/blog_59b189220100a49h.html 一、什么是对齐,以及为什么...
  • #pragma pack 设置内存对齐方式

    千次阅读 2012-10-31 08:20:19
    为了提高CPU的存储效率,编译器往往对class 和 struct ...来设置成 n字节的对齐方式   类中的static变量不会给类带来空间负担,也就是不被计算到类的大小中。   #include using namespace std; #pragma pack(4
  • 【1】内存对齐方式 C++代码: #pragma pack(push) #pragma pack(1) typedef struct _testStru2 { int iVal; char cVal; __int64 llVal; }testStru2; #pragma pack(pop) EXPORTDLL_API void Struct_...
  • 内存对齐方式的探究

    2011-08-02 21:29:24
    什么是对齐,以及为什么要对齐: 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型...
  • 具体的理论内容 神马是内存对齐以及为何要内存对齐请看http://blog.csdn.net/kokodudu/article/details/11918219 上面这个连接 将的相当理论 我给简化了一下 但是还是必须要看的 这里对如何计算结构体所占内存大小...
  • 内存对齐方式: 引用别人的总结:“假设我们同时声明两个变量: char a; short b; 用&(取地址符号)观察变量a, b的地址的话,我们会发现(以16位CPU为例): 如果a的地址是0x0000,那么b的地址将会是...
  • 最近闲来无事,翻阅msdn,在预编译指令中,翻阅到#pragma pack这个预处理指令,这个预处理指令为结构体内存对齐指令,偶然发现还有另外的内存对齐指令aligns(C++11),__declspec(align(#))(Microsoft专用),遂去探究...
  • 内存对齐,值得一读的内容, 内存对齐,值得一读的内容, 内存对齐,值得一读的内容, 内存对齐,值得一读的内容,
  • 内存对齐内存对齐规则解释、内存对齐原理

    千次阅读 多人点赞 2020-03-28 23:44:31
    一、内存对齐的原因 我们都知道计算机是以字节(Byte)为单位划分的,理论上来说CPU是可以访问任一编号的字节数据的,我们又知道CPU的寻址其实是通过地址总线来访问内存的,CPU又分为32位和64位,在32位的CPU一次...
  • 内存对齐3.1 结构体成员默认内存对齐3.2 不同架构内存对齐方式3.3 小试牛刀3.3.1 前置填充3.3.2 中间填充3.3.3 尾随填充 1. 同个结构体占用内存可变化      在 C语言之结构体 章节里,对struct的功能和使用进行...
  • 详细介绍了c++内存对齐的原因,内存是怎么对齐的
  • 内存对齐详解

    2019-01-13 17:31:45
    详细解读内存对齐原则,通过实例让你完全掌握内存对齐
  • 内存对齐以及如何关闭内存对齐

    千次阅读 2015-10-08 09:28:52
    内存对齐以前接触过,知道有这么回事,昨天面试,面试官问了一个结构体内存分配相关的问题: struct _A{ int a; int b; char c; }A; sizeof(A)=?(32位机器) 我一想这要涉及到内存对齐啊,sizeof(A)=12 啊, 没想到...
  • JNA入坑之内存对齐

    千次阅读 2019-09-08 15:41:55
    JNA的四种内存对齐方式 JNA提供了四种内存对齐的方式,分别是:ALIGN_DEFAULT、ALIGN_NONE、ALIGN_GNUC和ALIGN_MSVC。ALIGN_DEFAULT采用平台默认的对齐方式(推荐);ALIGN_NONE是不采用对齐方式;ALIGN_GNUC为针对...
  • C++ 内存对齐

    千次阅读 2019-10-22 15:02:47
    C++ 内存对齐,看下面三篇文章: C++内存对齐总结 vs2012编译器c++存储内存对齐情况详解 c++中的内存对齐
  • 关于内存对齐的很详细的解析.内容有什么是内存对齐,为什么需要内存对齐,编译器对内存对齐的处理,栈内存对齐等,并附有验证代码.值得一看.
  • C语言 | 内存对齐01 - 什么是内存对齐

    千次阅读 多人点赞 2021-08-12 22:40:50
    在单片机下使用C语言编程时,内存对齐的知识点必须掌握。掌握内存对齐后,可以防止内存碎片化,单片机有限的内存被更加有效地使用。 二、内存对齐 先看如下代码: 结构体Test1占用了多少字节?如果事先不知道内存...
  • 内存对齐

    千次阅读 2013-03-31 22:30:30
    今天复习了一下内存对齐的知识,觉得有必要记录一下。 我想对于大部分非C/C++程序员,程序的内存布局对他们来说都是透明的,他们不需要关系编译器是如何进行程序的内存管理的。应该上层以及都把这些封装好了。内存...
  • 内存对齐方式与原因
  • 什么是内存对齐?为什么要内存对齐

    万次阅读 多人点赞 2018-08-06 11:47:01
    要了解为什么要内存对齐,首先我们要了解什么是内存对齐 什么是内存对齐 关于什么是内存对齐,我们先来看几个例子 typedef struct { int a; double b; short c; }A; typedef struct { int a; short b; ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 159,253
精华内容 63,701
关键字:

内存对齐方式