如何计算:结构体内存的大小(在结构体的考察中占据非常重要的地位)

简介: 如何计算:结构体内存的大小(在结构体的考察中占据非常重要的地位)

在之前的文章中,笔者就结构体的简单定义,初始化,等内容,进行了简单描述!!但是,对于int  ,double ,float ,char 等类型都有自己的大小,但是,对于一个结构体,它的大小该如何计算呢???确实是一个疑问??这个也是不少老铁,在刚学结构体时候的最大煎熬!下面,笔者来带领大家熟悉一下,结构体大小的计算!!


在讲解之前,需要大家知道一下几点:


1.结构体的第一个成员,直接对齐到相对于结构体变量起始位置为0的偏移处!!


2.从第二个成员开始,要对齐到某个对齐数的整数倍的偏移处!


对齐数:结构体成员自身大小和默认对齐数的较小值!


在VS中,默认的对齐数为:8


在Linus环境不设默认对齐数(对齐数是结构体成员的自身的大小)


3.结构体的总大小,必须是最大对齐数的倍数!!每个结构体成员都有一个对齐数,其中最大的对齐数就是最大对齐数!!


4.如果嵌套结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小:就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍!


下面笔者用代码加解析的方法来演示一下:


#include <stdio.h>
struct s1
{
  char c1;
  int i;
  char c2;
};
int main()
{
  printf("%d\n", sizeof(struct s1));
  return 0;
}

上面定义了一个结构体,里面存放有:char c1;    int i;   char c2; (我们先注意一下,结构体里面的先后顺序) char 占一个字节,Int 占4个字节!但是对于运行结果:12个字节????什么鬼这是??


0a2653c851af460fa595bd959398a8f1.png


不相信的各位老铁,可以在VS的x86环境下进行实现!读者可以自己进行验证!!


2d65d23f6d4748949b924e4057485923.png


对于结构体的仔细划分为:


6de278e6d6694ce5bb08e7e842b7e74b.png


经过上面的笔者必须知道的部分:1,2,3,三点,我们可以有:


12c3b7f3f8814309a195c64f051d4445.png


但是,笔者将上面的结构体的顺序,稍微改写一下:


struct s2
{
  char c1;
  char c2;
  int i;
};

请注意一下,先后顺序!!


对于这个代码,该结构体的大小,又是多少呢???想必,到此为止,各位老铁,不再是:1+1+4=6个字节了吧!!


请看这代码的运行结果:


34e8d716411043c08c7ffba9fbba23de.png


但是,这个结果是8,这个又是为什么呢??各位老铁,可以根据,前面的那个案列来分析一下:


92ba0822ed0b46e1ae72df8a17d3a45b.png


对于上面两个案列的简单讲解,想必大家也能理解了:如何来求结构体大小的方法!!


下面,笔者来带领大家,求一下:结构体成员,相对于起始位置的偏移量!!


offset是一个宏!!是用来计算:结构体成员相对于起始位置的偏移量的一个宏!


使用语法为:


offsetof(type ,member);

type 是指:哪个结构体类型! ,member 是指:成员名!!


下面笔者用代码加解析的方式来带领大家了解一下:


#include <stdio.h>
#include <stddef.h>
struct s1
{
  char c1;
  int i;
  char c2;
};
int main()
{
  printf("%d\n", offsetof(struct  s1 , c1));   //0
  printf("%d\n", offsetof(struct  s1, i));     //4
  printf("%d\n", offsetof(struct  s1, c2));    //8
  return 0;
}


上面代码的运行结果为:


d79b274929334152a6d38be91e2d1be3.png


这个在,笔者的讲解过程:


dfc80ca9d8004e6c9ddc00e8448ffc6a.png


因此,结构体的总大小,必须是:最大对齐数的倍数!


同理可得,我们也可以对


struct s2
{
  char c1;
  char c2;
  int i;
};

来进行同样的道理分析:


#include <stdio.h>
#include <stddef.h>
struct s2
{
  char c1;
  char c2;
  int i;
};
int main()
{
  printf("%d\n", offsetof(struct  s2, c1));   //0
  printf("%d\n", offsetof(struct  s2, c2));     //1
  printf("%d\n", offsetof(struct  s2, i));    //4
  return 0;
}


0a2653c851af460fa595bd959398a8f1.png


想必现在,大家对于该结构体的大小,目前没有什么问题了吧!!


对于嵌套部分的结构体,我们一样可以用这样的方法来进行求解!!相信大家都是可以求出来的!!


经过上面的结构体对齐的方法讲解:想必大家也有着:为什么存在内存对齐??有着疑惑!!下面笔者来进行简单讲解一下:


1.平台原因


不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处,取某些特定类型的数据,否则,抛出硬件正常!


2.性能原因


数据结构(尤其是栈)应该尽可能地在自然边界上对齐,原因在于:为了访问未对其的内存,处理器需要做两次内存访问,而对齐的内存访问,仅需要访问一次!


总的来说:


结构体的内存对齐是拿空间换取时间的做法!


那么设计结构体的时候,我们既要满足对齐,又要节省空间,就要做到:


 让占用空间小的成员尽量集中在一起!!


相关文章
|
5月前
|
存储 安全 数据库
阿里云服务器计算型、通用型、内存型主要实例规格性能特点和适用场景汇总
阿里云服务器ECS计算型、通用型、内存型规格族属于独享型云服务器,在高负载不会出现计算资源争夺现象,因为每一个vCPU都对应一个Intel ® Xeon ®处理器核心的超线程,具有性能稳定且资源独享的特点。本文为大家整理汇总了阿里云服务器ECS计算型、通用型、内存型主要实例规格族具体实例规格有哪些,各个实例规格的性能特点和主要适用场景。
阿里云服务器计算型、通用型、内存型主要实例规格性能特点和适用场景汇总
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
122 13
|
1月前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
62 11
|
1月前
|
编译器 Go
探索 Go 语言中的内存对齐:为什么结构体大小会有所不同?
在 Go 语言中,内存对齐是优化内存访问速度的重要概念。通过调整数据在内存中的位置,编译器确保不同类型的数据能够高效访问。本文通过示例代码展示了两个结构体 `A` 和 `B`,尽管字段相同但排列不同,导致内存占用分别为 40 字节和 48 字节。通过分析内存布局,解释了内存对齐的原因,并提供了优化结构体字段顺序的方法,以减少内存填充,提高性能。
42 3
|
1月前
|
存储 Java 程序员
结构体和类的内存管理方式在不同编程语言中的表现有何异同?
不同编程语言中结构体和类的内存管理方式既有相似之处,又有各自的特点。了解这些异同点有助于开发者在不同的编程语言中更有效地使用结构体和类来进行编程,合理地管理内存,提高程序的性能和可靠性。
31 3
|
1月前
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
1月前
|
存储 缓存 算法
结构体和类在内存管理方面有哪些具体差异?
【10月更文挑战第30天】结构体和类在内存管理方面的差异决定了它们在不同的应用场景下各有优劣。在实际编程中,需要根据具体的需求和性能要求来合理选择使用结构体还是类。
|
4月前
|
存储 Go
Go 内存分配:结构体中的优化技巧
Go 内存分配:结构体中的优化技巧
|
5月前
|
设计模式 并行计算 安全
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
56 0
|
1月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
291 1

热门文章

最新文章