学习
实践
活动
专区
工具
TVP
写文章

C语言笔记】结构内存对齐

先看一个结构体: typedef struct Test { char a1; int a2; char a3; short a4; }Test_T; 在32位编译系统下这一个结构体的字节数是多少呢 因为编译器会对不足4字节的变量空间自动补齐为4个字节(这就是内存对齐),以提高CPU的寻址效率(32位CPU以4个字节步长寻址的)。 内存对齐是编译器的“管辖范围”。 可见,正好印证了上述的说法,补齐之后结构体成员a1,a2,a3的地址之间正好相差4个字节,a3与a4之间相差两个字节也是因为在其中多留出了1个空白字节。该程序的运行结果可形象地描述为下图: ? a1只占用一个字节,为了内存对齐保留了三个空白字节;a3和a4加起来共3字节,为了内存对齐保留了1个空白字节。这就是编译器存储变量时做的见不得人的”手脚“,以方便其雇主——CPU能更快地找到这些变量。

38420

详细解读C语言结构体的内存对齐

前言本文介绍结构体相关的偏移量、对齐数、对齐规则、内存对齐存在的原因、修改对齐数等知识点~偏移量在知道结构体如何对齐之前,需要知道什么是结构体的偏移量。 而我们刚才算出来的12刚好是4的倍数,因此这个结构体的大小就是12字节。存在的原因既然内存对齐这么麻烦,这么浪费空间,那么为什么要创造出这么个东西呢?现在广为流传的一共有两个原因:一、移植原因。 总的来说,内存对齐是一种拿空间换取时间的行为。 都不想放过如果你既想按照内存规则的方式来,还想让内存占用达到最小,就应该让占用内存小的成员变量尽可能靠在一起,像这样:struct S1{char c1;int i;char c2;};struct S2 {char c1;char c2;int i;};这两种类型,只有成员变量的顺序不同,但结构体占用的总大小也有所不同。

4860
  • 广告
    关闭

    新年·上云精选

    热卖云产品新年特惠,2核2G轻量应用服务器9元/月起,更多上云必备产品助力您轻松上云

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    内存篇:JVM内存结构

    Java8相对之前的版本,JVM结构发生了较大的变化,取消了永久代,新增了元空间,同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。 下面,以Java8为例,对JVM结构做一番总结。 1 JVM结构详解 首先,看下最新的JVM结构图: ? 很多开发人员会把Java内存分为堆内存(Heap)和栈内存(Stack),这种划分的流行只能说明大多数开发人员最关注、与对象内存分配关系最密切的内存区域是这两块,其中所指的“堆”在后面会讲到,而所指的“ 小结 经过上面的讲解,想必大家已经了解到JVM内存结构的基本情况。下面对照脑图,归纳总结一下,看你能说出来多少。 ? 同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。 ? 本地内存(Native memory),也称为C-Heap,是供JVM自身进程使用的。

    2.4K30

    JVM内存结构

    按照Java虚拟机规范的规定, JVM自动管理的内存将包括以下几个运行时的数据区域: ? 下面分别对几个数据区域进行说明: 1.程序计数器 程序计数器是JVM中一块较小的内存区域, 保存着当前线程执行的虚拟机字节码指令的内存地址. 所有虚拟机栈也是"线程私有"的内存区域. 这个栈中对应多个栈帧, 每调用一个方法就会往栈中创建并压入一个栈帧, 栈帧是用来存储方法数据和部分过程结果的数据结构, 每一个方法从调用到最终返回结果的过程, 就对应一个栈帧从入栈到出栈的过程. , 就会出现OOM 3.本地方法栈 本地方法栈和虚拟机栈的作用相似, 只是虚拟机栈是为Java方法服务的, 而本地方法栈是为Native方法服务的. 4.方法区 方法区是用来存储类结构信息(包括常量池、

    21620

    JVM:内存结构

    JVM的内存结构大概分为: ? 通过一张图来了解如何通过参数来控制各区域的内存大小 ? 控制参数 -Xms设置堆的最小空间大小。 -Xmx设置堆的最大空间大小。 本地方法栈(C栈) 本地方法栈:是描述 Native方法运行过程的线程内存模型。是为 JVM 运行 Native 方法准备的空间。 由于很多 Native 方法都是用 C 语言实现的,所以它通常又叫 C 栈。它与Java 虚拟机栈实现的功能类似,只不过本地方法栈是描述本地方法运行过程的线程内存模型。 同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。 ? 本地内存(Native memory),也称为C-Heap,是供JVM自身进程使用的。 直接内存的分配不受Java堆大小的限制,但是,既然是内存则肯定还是会受到本机总内存的限制。

    33921

    JVM 内存结构

    对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像 C/C++程序开发程序员这样为每一个 new 操作去写对应的delete/free 操作,不容易出现内存泄漏和内存溢出问题。 进一步划分的目的是更好地回收内存,或者更快地分配内存。 ? Java 栈可用类比数据结构中栈,Java 栈中保存的主要内容是栈帧,每一次函数调用都会有一个对应的栈帧被压入Java栈,每一个函数调用结束后,都会有一个栈帧被弹出。 直接内存 ---- 直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 OutOfMemoryError 异常出现。 本机直接内存的分配不会收到 Java 堆的限制,但是,既然是内存就会受到本机总内存大小以及处理器寻址空间的限制。

    17520

    JVM 内存结构

    Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分为若干个不同的数据区域。 ? 这些区域中,一些是线程私有的,一些是线程共享的。 线程私有的:程序计数器、虚拟机栈、本地方法栈 线程共享的:堆、方法区、直接内存 1、程序计数器 一块较小的内存空间,用于标记当前线程所执行字节码的行号。 所有实例和数组都在这里分配内存,也是线程共享的内存区域。 -Xms 设置最小值;-Xmx 设置最大值。 堆内存分配会另写一篇文章介绍。 6、直接内存 直接内存并不是虚拟机内存的一部分,也不是 Java 虚拟机规范中定义的内存区域。 jdk1.4 中新加入的 NIO,引入了通道与缓冲区的 IO 方式,它可以调用 Native 方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小。

    29420

    jvm内存结构

    JVM内存结构概览 先来看一张图: jvm主要分,堆、方法区、java栈、本地方法栈、程序计数器五个区域,其中方法区和堆区是线程共享的 堆区域 堆内存是JVM中最大的一块由新生代和老年代组成,而新生代内存又被分成三部分 TLAB仍然分配在堆上,结构比较简单,start、end就是起止地址,top表示已经分配到那里了,top与end相遇的时候,代表该缓存已经满了,JVM会试图再从Eden中分配一块 老年代 (old) , 这样在一些场景中显著提升内存, 避免了在java堆和native堆中来回复制数据 直接内存的分配不受java堆大小的限制, 但是配置虚拟机参数的时候要考虑到直接内存的存在, 不能让各个内存区域的总和大于物理机的内存 内存泄露: memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光 内存泄露处理方式 如果是内存泄露,可用 具体可以参考分析内存泄露的一般办法 内存溢出的处理方式 如果内存不泄露,也就是说,就是内存中的对象确实都还必须都活着,则: 检查虚拟机的堆参数(-Xmx与-Xms),与机器物理内存对比看是否还可以调大。

    37720

    JVM内存结构

    **主要结构:**堆内存、方法区、栈(说明:基于JDK1.7) 堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden空间、From Survivor空间、To Survivor 在虚拟机规范中对本地方法栈中方法使用的语言、使用方式 与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。 此内存区域的唯一目的就 是存放对象实例,几乎所有的对象实例都在这里分配内存。 七、直接内存 直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规 范中定义的内存区域。 服务器管理员在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略 直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制), 从而导致动态扩展时出现OutOfMemoryError

    4720

    CPU内存结构

    开局一张图 由于CPU频率太快了,为解决直接读取内存的数据上的延迟,在CPU和内存之间,存在3级缓存。 ? ? 缓存某个缓存行和主存数据的不一致,该缓存行需要在未来某个时间点回写主存,回写之后状态变为(exclusive 独享) E:(exclusive 独享)CPU缓存中的某个缓存行和主存数据一致,处于这个状态的可以被其他CPU读取内存时变成 总线锁 MESI协议之前,解决缓存一致性方案是总线锁机制,这种方案比较低效,锁期间,其他CPU无法访问内存。 CPU乱序 多核时代,处理器为提高运算速度,可能作出违背代码原有初衷的行为。 解决这种问题的方式就是内存屏障,简单点说是不同的处理器架构提供了不同指令集用来建立内存屏障,这样控制不可乱序。

    31220

    JVM 内存结构

    Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分为若干个不同的数据区域。 ? 这些区域中,一些是线程私有的,一些是线程共享的。 线程私有的:程序计数器、虚拟机栈、本地方法栈 线程共享的:堆、方法区、直接内存 1、程序计数器 一块较小的内存空间,用于标记当前线程所执行字节码的行号。 所有实例和数组都在这里分配内存,也是线程共享的内存区域。 -Xms 设置最小值;-Xmx 设置最大值。 堆内存分配会另写一篇文章介绍。 6、直接内存 直接内存并不是虚拟机内存的一部分,也不是 Java 虚拟机规范中定义的内存区域。 jdk1.4 中新加入的 NIO,引入了通道与缓冲区的 IO 方式,它可以调用 Native 方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小。

    63230

    CPU内存结构

    开局一张图 由于CPU频率太快了,为解决直接读取内存的数据上的延迟,在CPU和内存之间,存在3级缓存。 ? ? 缓存某个缓存行和主存数据的不一致,该缓存行需要在未来某个时间点回写主存,回写之后状态变为(exclusive 独享) E:(exclusive 独享)CPU缓存中的某个缓存行和主存数据一致,处于这个状态的可以被其他CPU读取内存时变成 总线锁 MESI协议之前,解决缓存一致性方案是总线锁机制,这种方案比较低效,锁期间,其他CPU无法访问内存。 CPU乱序 多核时代,处理器为提高运算速度,可能作出违背代码原有初衷的行为。 解决这种问题的方式就是内存屏障,简单点说是不同的处理器架构提供了不同指令集用来建立内存屏障,这样控制不可乱序。

    80210

    JVM 内存结构

    本地方法栈(C 栈) 本地方法栈的定义 本地方法栈是为 JVM 运行 Native 方法准备的空间,由于很多 Native 方法都是用 C 语言实现的,所以它通常又叫 C 栈。 直接内存(堆外内存) 直接内存是除 Java 虚拟机之外的内存,但也可能被 Java 使用。 操作直接内存 在 NIO 中引入了一种基于通道和缓冲的 IO 方式。 直接内存的大小不受 Java 虚拟机控制,但既然是内存,当内存不足时就会抛出 OutOfMemoryError 异常。 直接内存与堆内存比较 直接内存申请空间耗费更高的性能 直接内存读取 IO 的性能要优于普通的堆内存。 直接内存作用链:本地 IO -> 直接内存 -> 本地 IO 堆内存作用链:本地 IO -> 直接内存 -> 非直接内存 -> 直接内存 -> 本地 IO 服务器管理员在配置虚拟机参数时,会根据实际内存设置

    22620

    JVM之JVM运行时内存结构, JDK1.7 JVM内存结构, JDK1.8 JVM内存结构, JVM堆内存结构

    1 JDK1.7结构 1.1 JVM内存图 程序计数器: 线程私有的(每个线程都有一个自己的程序计数器), 是一个指针. 代码运行, 执行命令. 方法区: 线程共享的(所有的线程共享一份), .class的信息, 类的信息, 方法的定义, 常量池, 静态变量等. 1.2 JDK1.7 堆内存结构 Young 年轻区(代) Young区被划分为三部分 Virtual区: 最大内存和初始内存的差值,就是Virtual区。 这里提到的GC咱们后续继续介绍~ 2. JDK1.8 结构 2.1 JVM运行时内存图 JDK1.8和JDK1.7的jvm内存最大的区别是, 在1.8中方法区是由元空间(元数据区)来实现的,常量池移到堆中. 1.8不存在方法区,将方法区的实现给去掉了 元空间: 存储.class 信息, 类的信息,方法的定义,静态变量等.而常量池放到堆里存储 2.2 JDK1.8堆内存结构 由上图可以看出,jdk1.8的内存模型是由2部分组成, 年轻代+年老代.

    10110

    C语言 | 关于结构内存对齐,看这篇就够了

    C语言当中的结构内存对齐基本上是笔试中必考的问题,一般都是给你一个结构体,问你这个结构体占用多少个字节。今天就来深入分析一下可能涉及到的各种情况。 首先来说一下结构体的对齐规则。 一、结构体对齐规则首先要看有没有用#pragma pack宏声明,这个宏可以改变对齐规则,有宏定义的情况下结构体的自身宽度就是宏上规定的数值大小,所有内存都按照这个宽度去布局(这样说其实不太严谨,后面会提到 struct test { char a; //1 char b; //1 char c; //1 }; 这个结构体占几个字节呢?答案是3个。 这样,a和b就占了4个字节了,接下来c占一个字节。但是,还没完,看第三条规则,结构体的总大小,为其成员中所含最大类型的整数倍。所以,在这个例子中,结构体总大小应该要为2的整数倍,所以是6,而不是5。 在32位cpu上选择缺省对齐的情况下,有如下结构体定义: struct test { char a : 7; int b : 11; int c : 4; int d : 10;

    7.4K40

    关注

    腾讯云开发者公众号
    10元无门槛代金券
    洞察腾讯核心技术
    剖析业界实践案例
    腾讯云开发者公众号二维码

    相关产品

    • TDSQL-C MySQL 版

      TDSQL-C MySQL 版

      TDSQL-C是腾讯云自研的新一代高性能高可用的企业级数据库。云原生数据库的数据库架构将传统数据库与云计算的优势相结合,完全兼容MySQL和PostgreSQL,具有更高的性价比,更灵活的弹性扩展,可实现超百万级QPS的高吞吐,128TB海量分布式智能存储。

    相关资讯

    热门标签

    活动推荐

    扫码关注腾讯云开发者

    领取腾讯云代金券