当前位置: 首页 > news >正文

golang 内存对齐和填充规则

内存对齐和填充规则

  1. 对齐要求:每个数据类型的起始地址必须是其大小的倍数。

    • int8(1字节):不需要对齐。
    • int16(2字节):起始地址必须是2的倍数。
    • int32(4字节):起始地址必须是4的倍数。
    • int64(8字节):起始地址必须是8的倍数。
  2. 填充规则:如果当前偏移量不是下一个成员变量对齐要求的倍数,则编译器会在前一个成员后插入“填充字节”,以使下一个成员的起始地址满足对齐要求。

  3. 结构体总大小:结构体的总大小必须是其最大成员对齐大小的倍数,必要时会在结构体末尾添加额外的填充字节。

示例解析

示例 1:未优化的结构体
type Unoptimized struct {
    a int8   // 1 byte
    b int32  // 4 bytes, 需要4字节对齐
    c int16  // 2 bytes, 需要2字节对齐
}
  • a 占用 1 字节,起始地址为 0。
  • b 需要 4 字节对齐,但 a 只占用了 1 字节,因此在 a 后面需要填充 3 字节,使得 b 的起始地址为 4。
  • c 需要 2 字节对齐,b 占用 4 字节,所以 c 的起始地址为 8,不需要额外填充。
  • 结构体总大小为 10 字节(1 + 3 + 4 + 2),但为了使结构体大小为 4 字节对齐(最大成员 b 是 4 字节对齐),需要在末尾再填充 2 字节。

最终结构体大小为 12 字节。

示例 2:优化后的结构体
type Optimized struct {
    b int32  // 4 bytes, 需要4字节对齐
    c int16  // 2 bytes, 需要2字节对齐
    a int8   // 1 byte, 不需要对齐
}
  • b 占用 4 字节,起始地址为 0,符合 4 字节对齐。
  • c 需要 2 字节对齐,b 占用 4 字节,所以 c 的起始地址为 4,不需要额外填充。
  • a 占用 1 字节,c 占用 2 字节,所以 a 的起始地址为 6,不需要额外填充。
  • 结构体总大小为 7 字节(4 + 2 + 1),但为了使结构体大小为 4 字节对齐(最大成员 b 是 4 字节对齐),需要在末尾再填充 1 字节。

最终结构体大小为 8 字节。

图解填充规则

假设我们有一个结构体:

type Example struct {
    a int8   // 1 byte
    b int16  // 2 bytes
    c int32  // 4 bytes
}

我们可以用图来表示内存布局:

Offset: 0  1  2  3  4  5  6  7  8  9 10 11
        +--+--+--+--+--+--+--+--+--+--+--+--+
        | a| P| P| P| b| b| P| P| c| c| c| c|
        +--+--+--+--+--+--+--+--+--+--+--+--+
  • a 占用 1 字节,后面填充 3 字节(P 表示填充字节)。
  • b 占用 2 字节,后面填充 2 字节。
  • c 占用 4 字节。

调整顺序后:

type Example struct {
    c int32  // 4 bytes
    b int16  // 2 bytes
    a int8   // 1 byte
}

内存布局变为:

Offset: 0  1  2  3  4  5  6  7
        +--+--+--+--+--+--+--+--+
        | c| c| c| c| b| b| a| P|
        +--+--+--+--+--+--+--+--+
  • c 占用 4 字节。
  • b 占用 2 字节。
  • a 占用 1 字节,后面填充 1 字节。

最终结构体大小为 8 字节,比原来的 12 字节更紧凑。

总结

通过将占用较大内存空间的成员放在前面,可以减少编译器为了对齐而插入的填充字节数量,从而使结构体更加紧凑,节省内存。你可以使用 unsafe.Sizeof()unsafe.Alignof() 来验证这些结构体的实际大小和对齐方式。

相关文章:

  • 【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
  • uvm中的run_test作用
  • C语言基础要素(007):使用变量
  • 自然语言处理NLP入门 -- 第十节NLP 实战项目 2: 简单的聊天机器人
  • uniapp 系统学习,从入门到实战(六)—— 样式与布局
  • [思考记录]AI时代下,悄然的改变
  • 大白话前端性能优化方法的分类与具体实现
  • Python 科学计算生态入门 2 - NumPy 基础与示例
  • Numpy基础知识
  • Highcharts 配置语法详解
  • redis repl_backlog_first_byte_offset 这个字段的作用
  • 安装 Windows Docker Desktop - WSL问题
  • NAT 代理服务 内网穿透
  • 【SQL】MySQL中的字符串处理函数:concat 函数拼接字符串,COALESCE函数处理NULL字符串
  • 详解ESP32使用select函数来监听串口数据
  • 99分巧克力
  • Python可视化大框架的研究与应用
  • Python大战Java:AI时代的编程语言‘复仇者联盟‘能否换C位?
  • Uniapp开发微信小程序插件的一些心得
  • AI Agent 定义与核心要素详解
  • 做网站用什么代码编写/网站seo检测工具
  • 上海网站建设q479185700棒/找回原来的百度
  • 网站地区词优化/百度灰色关键词排名
  • 做的好的区块链网站/企业宣传片制作
  • 电商网站前端源码/百度贴吧热线客服24小时
  • 东莞网站建设音乐盒/焦作网站seo