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

数据结构 / 结构体字节计算

1. 结构体的存储

  • 结构体各个成员的地址是连续的
  • 结构体变量的地址是第一个成员的地址

2. 64位操作系统8字节对齐

  • 结构体的总字节大小是各个成员字节的总和,字节的总和需要是最宽成员的倍数
  • 结构体的首地址是最宽成员的倍数
  • 结构体各个成员的偏移量是该成员字节的倍数,否则填充空字节

例子1:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>struct A
{int a; //4 char b; //1 short c; //2 float d; //4 }a;int main(int argc, const char *argv[])
{printf("a=%p\n", &a);printf("a.a=%p\n", &a.a);printf("a.b=%p\n", &a.b);printf("a.c=%p\n", &a.c);printf("a.d=%p\n", &a.d);printf("sizieof(a)=%ld\n", sizeof(a));return 0;
}          

计算

运行结果

a=0x55b0037eb018
a.a=0x55b0037eb018
a.b=0x55b0037eb01c
a.c=0x55b0037eb01e
a.d=0x55b0037eb020
sizieof(a)=12

例子2:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>struct A
{int *a; //8 char b; //1 double c; //8 long d; //8 } s1; int main(int argc, const char *argv[])
{printf("s1=%p\n", &s1);printf("s1.a=%p\n", &s1.a);printf("s1.b=%p\n", &s1.b);printf("s1.c=%p\n", &s1.c);printf("s1.d=%p\n", &s1.d);printf("sizieof(s1)=%ld\n", sizeof(s1));return 0;
}  

计算

运行结果

s1=0x55e754e4e040
s1.a=0x55e754e4e040
s1.b=0x55e754e4e048
s1.c=0x55e754e4e050
s1.d=0x55e754e4e058
sizieof(s1)=32

例子3:

#include <string.h>                                                                       
#include <stdlib.h>
#include <stdio.h>struct S
{char a[5]; //int b; //} s3; int main(int argc, const char *argv[])
{printf("s3=%p\n", &s3);printf("s3.a=%p\n", &s3.a);printf("s3.b=%p\n", &s3.b);printf("sizieof(s3)=%ld\n", sizeof(s3));return 0;
}

计算

运行结果

s3=0x55da08b43018
s3.a=0x55da08b43018
s3.b=0x55da08b43020
sizieof(s3)=12

3. 32位操作系统,4字节对齐:

  • 结构体的总字节大小是各个成员字节的总和,字节的总和需要是最宽成员的倍数
    • 如果最宽成员是1,则是1的倍数
    • 如果最宽成员是2,则是2的倍数
    • 如果最宽成员是4,8,则是4的倍数
  • 结构体的首地址是最宽成员的倍数
  • 结构体各个成员的偏移量是该成员字节的倍数,否则填充空字节
    • 如果成员字节是1,则偏移量是1的倍数
    • 如果成员字节是2,则偏移量是2的倍数
    • 如果成员字节是4,8,则偏移量是4的倍数

例子4:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>struct S5
{char a; //int *b; double c;long d;}s5 ;struct S6
{char e[5];struct S5 s5; int f;}s6;int main(int argc, const char *argv[])
{printf("s6.e=%p\n", &s6.e);printf("s6.s5.a=%p\n", &s6.s5.a);printf("s6.s5.b=%p\n", &s6.s5.b);                                                     printf("s6.s5.c=%p\n", &s6.s5.c);printf("s6.s5.d=%p\n", &s6.s5.d);printf("s6.f=%p\n", &s6.f);printf("sizieof(s6)=%ld\n", sizeof(s6));return 0;
}
~    

计算

运行结果

s6.e=0x565cf040
s6.s5.a=0x565cf048
s6.s5.b=0x565cf04c
s6.s5.c=0x565cf050
s6.s5.d=0x565cf058
s6.f=0x565cf05c
sizieof(s6)=32

http://www.lryc.cn/news/246363.html

相关文章:

  • rancher2.6 docker版本部署
  • UE5人物残影学习(材质实现)
  • Spring Boot 内置工具类
  • C语言--每日选择题--Day27
  • 黑马程序员索引学习笔记
  • 新手如何对一个web网页进行一次渗透测试
  • vs2019 - MFC对话框程序的工程名称不支持下划线命名法
  • java JDBCUtils 使用静态代码块连接数据库 全程值保持一次连接
  • 剑指 Offer(第2版)题解(C++ Version)
  • 6.15合并二叉树(LC617-E)
  • 百度智能小程序系统源码+关键词排名优化 附带完整的搭建教程
  • 2019年11月7日 Go生态洞察:Go Modules v2及更高版本
  • vue3通过provide和inject实现多层级组件通信
  • 【Java学习笔记】72 - 满汉楼 - 餐饮管理系统
  • 【我的创作纪念日】
  • 车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体)
  • 使用Pytorch从零开始构建Energy-based Model
  • 基于C#实现梳排序
  • 盘点72个Android系统源码安卓爱好者不容错过
  • nodejs+vue+elementui足球篮球联赛系统
  • 18.Oracle的过程和函数
  • A JSONObject text must begin with ‘{‘ at 1 [character 2 line 1]
  • C#中openFileDialog控件的使用方法
  • 多线程04 死锁,线程可见性
  • java中文转拼音(去除音调)
  • [Android]常见的数据传递方式
  • <蓝桥杯软件赛>零基础备赛20周--第7周--栈和二叉树
  • 探究Kafka原理-7.exactly once semantics 和 性能测试
  • 【密码学引论】序列密码
  • 知识变现的未来:解析知识付费系统的核心