结构体占用内存大小如何确定?-->结构体字节对齐 | C语言

news2024/11/18 5:34:15

目录

一、什么是结构体

二、为什么需要结构体

三、结构体的字节对齐

3.1、示例1

3.2、示例2

3.3、示例3

 3.4、示例4

3.5、示例5

四、结构体字节对齐总结


一、什么是结构体

        结构体是将不同类型的数据按照一定的功能需 求进行整体封装,封装的数据类型与大小均可以由用户指定。

结构体定义,如下图1:

 

图1

二、为什么需要结构体

        当需要存储大量重复的信息时,比如存储一个班级学生的信息,肯定包括姓名、学号、性别、年龄、成绩、家庭地址等项。这些项都是具有内在联系的,它们是一个整体,都表示同一个学生的信息。但如果将它们定义成相互独立的变量的话,就无法反映它们的内在联系,如下图2:

 图2

        如果只是这样写的话,只是定义了一个学生,如果要定义第二个学生就要再写一遍。这样不仅麻烦,而且很容易混淆。要是能定义一个变量,而且这个变量正好包含这六个项,即将它们合并成一个整体的话就好了。结构体就是为了解决这个问题而产生的。

三、结构体的字节对齐

现在来探讨一个问题,结构体的大小是如何划分的呢?

3.1、示例1

        有这样一个程序,结构占用内存大小按理来说应该是,char占1个字节,int占4个字节,1+4=5,结构体占用内存大小应该是5个字节才对。

#include <stdio.h>

struct STUDENT
	{
		char a;
		int b;
	}data;

int main()
{
	printf("a的地址为:%p,b的地址为:%p\n", &data.a, &data.b);  //%p是取地址符
	printf("结构体总大小为:%d\n", sizeof(data));
   
   return 0;
}

以上程序输出结果如下图3所示:

图3

内存分配图下图4:

        图4

分析:

        事实上结构体大小是8个字节,b占4字节我们能理解,但a是char型,char型不是占1字节吗,这里为什么占4字节?其实不是它占了4字节,它占的还是1字节,只不过结构体中有一个字节对齐的概念。


那么到底是怎么存储的呢?


        就是按字节对齐的方式存储的!即以结构体成员中占内存最多的数据类型所占的字节数为标准,所有的成员在分配内存时都要与这个长度对齐。


        以上面这个程序为例,结构体变量data的成员中占内存最多的数据类型是int型,其占4字节的内存空间,那么所有成员在分配内存时都要与4字节的长度对齐。也就是说,虽然char只占1字节,但是为了与4字节的长度对齐,它后面的3字节都会空着。


3.2、示例2

         按上面的结论,最大的是int占4个字节,那么按4字节对齐,大小应该是4+4+4=12;

#include <stdio.h>

struct STUDENT
	{
		char a;
		cahr c;
		int b;
	}data;

int main()
{
	printf("a的地址为:%p,b的地址为:%p,c的地址为:%p\n", &data.a, &data.b, &data.c);
	printf("结构体总大小为:%d\n", sizeof(data));
   
   return 0;
}

结果如下图5:

图5


 但大小实际上并没有变化,内存分配为下图6所示:

图6


分析:

        在分配了a的内存后,c希望和a近邻,并且因为内存对齐a申请了4个字节,在a相邻的位置可以存放,所以c与a共同占用一个4字节内存。

3.3、示例3

        首先最长的数据类型占4字节,所以是以4字节对齐。1+1+1+1+4+4=12

#include <stdio.h>

struct STUDENT
	{
		char a;
		char c;
		char d;
		char f;
		char e;
		int b;
	}data;

int main()
{
	printf("a的地址为:%p,b的地址为:%p,c的地址为:%p,d的地址为:%p,f的地址为:%p,e的地址为:%p\n", &data.a, &data.b, &data.c, &data.d, &data.f, &data.e);
	printf("结构体总大小为:%d\n", sizeof(data));
   
   return 0;
}

输出结果如下图7:

图7


即该结构体变量分配内存时如下图8:

图8

分析:

        首先最长的数据类型占4字节,所以是以4对齐。a占1字节,b接在a后面占1字节,c接在b后面占1字节,d接在c后面占1字节,此时满4字节了,e再来就要另起一行。f想紧接着e后面分配,但e后面还剩3字节,小于int类型的4字节,所以f另起一行。

 3.4、示例4

        首先最长的数据类型占4字节,所以是以4字节对齐。4+4+4=12。

#include <stdio.h>

struct STUDENT
	{
		char a;
		int c;
		char b;
	}data;

int main()
{
	printf("a的地址为:%p,b的地址为:%p,c的地址为:%p\n", &data.a, &data.b, &data.c);
	printf("结构体总大小为:%d\n", sizeof(data));
   
   return 0;
}

输出结果如下图9:

图9


内存分配如下图10:

图10

分析:

        首先最长的数据类型占4字节,所以是以4对齐。a占1字节,c希望与a近邻,但3字节不足以存放int,故重新再起一行,所以a占4字节。b也希望与a近邻,但a空间不足以存放b,故b也重新起一行占4个字节。

 

3.5、示例5

        首先最长的数据类型占4字节,所以是以4字节对齐。但出现了数组,大小应该怎样计算呢?

#include <stdio.h>

struct STUDENT
{
	char name[3];
	int age;
	char sex;
	char score;
}data;


int main()
{
	printf("%p,%p,%p,%p,%p,%p\n", &data.name[0], &data.name[1], &data.name[2], &data.age, &data.sex, &data.score);
	printf("结构体总大小为:%d\n", sizeof(data));
   
   return 0;
}

输出结果如下图11:

 图11

分析:

        出现了数组,数组可以看做多个char类型,依然是占1字节,所以内存大小为:4+4+4=12。

四、结构体字节对齐总结

概念总结:

        1)可以知道,同样的数据类型,只不过交换了一下位置,结构体变量data所占的内存空间就由8字节变成12字节,多了4字节。这就告诉我们,在声明结构体类型时,各类型成员的前后位置会对该结构体类型定义的结构体变量所占的字节数产生影响;

        2)没有规律的定义会增加系统给结构体变量分配的字节数,降低内存分配的效率。但这种影响对操作系统来说几乎是可以忽略不计的!所以我们在写程序的时候,如果有心的话,声明结构体类型时就按成员类型所占字节数从小到大写,或从大到小写;

        3)但是如果没有按规律书写的话也不要紧,声明结构体类型时并非一定要从小到大声明,只是为了说明结构体字节对齐这个概念。

使用总结:

        1)按占用最大的字节对齐;

        2)占用内存可以共用(前提是足以同时保存);

        3)不足以存放时,会出现申请一个内存空间;

        4)合理书写顺序可以节省CPU资源,当量足够大时,有可能会影响系统运行效率。

        如果在单片机使用RTOS,RTOS管理的内存空间固定,但因为结构体申请了很多内存,在使用时,有可能因为内存不足而产生不必要的错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/380791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

日期:Date,SimpleDateFormat常见API以及包装类

一.Date类 package com.gch.d1_date;import java.util.Date;/**目标:学会使用Date类处理时间,获取时间的信息*/ public class DateDemo1 {public static void main(String[] args) {// 1.创建一个Date类的对象:代表系统此刻日期时间对象Date d new Date();System.out.println(…

什么是pod类型

很久很久以前&#xff0c;C 语言统一了江湖。几乎所有的系统底层都是用 C 写的&#xff0c;当时定义的基本数据类型有 int、char、float 等整数类型、浮点类型、枚举、void、指针、数组、结构等等。然后只要碰到一串01010110010 之类的数据&#xff0c;编译器都可以正确的把它解…

做软件测试,如何才能实现月入20K?

听我的&#xff0c;测试想要月入20k。 首先你要去大厂&#xff0c;不在大厂起码也得在一线城市&#xff0c;北上广深。 二线城市的话成都、杭州最好。 不然的话想都不要想。 像我之前整理过成都的公司&#xff0c;除了字节跳动、蚂蚁金服、滴滴、美团、京东、平安、字节跳动…

超简单的计数排序!!

假设给定混乱数据为&#xff1a;3&#xff0c;0&#xff0c;1&#xff0c;3&#xff0c;6&#xff0c;5&#xff0c;4&#xff0c;2&#xff0c;1&#xff0c;9。 下面我们将通过使用计数排序的思想来完成对上面数据的排序。(先不谈负数) 计数排序 该排序的思路和它的名字一样…

Java——图像渲染

题目链接 leetcode在线oj题——图像渲染 题目描述 有一幅以 m x n 的二维整数数组表示的图画 image &#xff0c;其中 image[i][j] 表示该图画的像素值大小。 你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。 为了完成…

互联网医院系统软件开发|互联网医院管理系统开发的好处

互联网医院一直是现在的热门行业&#xff0c;很多的医院已经开发了互联网医院&#xff0c;并且已经在良好的运行中&#xff0c;而有一些医院和企业正在开发中&#xff0c;或者打算开发互联网医院系统&#xff0c;其实这些企业和医院还是很有远见的&#xff0c;因为他们知道并了…

Swift 第三方 播放器AliyunPlayer(阿里云播放器)(源码)

一直觉得自己写的不是技术&#xff0c;而是情怀&#xff0c;一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的&#xff0c;希望我的这条路能让你们少走弯路&#xff0c;希望我能帮你们抹去知识的蒙尘&#xff0c;希望我能帮你们理清知识的脉络&#xff0…

卡尔曼滤波——一种基于滤波的时序状态估计方法

文章目录1. Kalman滤波及其应用2. Kalman原理公式推导&#xff1a;Step 1&#xff1a;模型建立Step 2&#xff1a;开始Kalman滤波Step 3&#xff1a;迭代滤波本文是对 How a Kalman filter works, in pictures一文学习笔记&#xff0c;主要是提炼核心知识&#xff0c;方便作者快…

已解决pip install wxPython模块安装失败

已解决&#xff08;pip install wxPython安装失败&#xff09;error: legacy-instal1-failure Encountered error while trying to install package.wxPython note: This is an issue with the package mentioned above&#xff0c;not pip. hint : See above for output from …

如何用AST还原某音的JSVMP

1. 什么是JSVMP vmp简单来说就是将一些高级语言的代码通过自己实现的编译器进行编译得到字节码&#xff0c;这样就可以更有效的保护原有代码&#xff0c;而jsvmp自然就是对JS代码的编译保护&#xff0c;具体的可以看看H5应用加固防破解-JS虚拟机保护方案。 如何区分是不是jsv…

OpenFeign 切换HttpClient遇到的问题

背景 OpenFeign支持三种Http请求方式&#xff0c;默认情况下通过jdk中的HttpURLConnection向下游服务发起http请求&#xff08;详见下图&#xff0c;源码详见feign.Client.Default&#xff09;&#xff0c; 默认的Client 采用 HttpURLConnection&#xff0c; 这种是无法复用的…

为什么一定要做集成测试?

集成测试&#xff0c;我们都不陌生&#xff0c;几乎我们产品每天都在进行。但是我们真的有好好思考&#xff1a;为什么一定要做集成测试吗&#xff1f;只是为了简单的将“积木”搭起来就行&#xff0c;还是有什么其他的深意&#xff1f; 深意可能不一定会有&#xff0c;但是意…

qt5.15 快速安装 国内源

1 qt5.15 安装问题 最大的问题就是需要在线下载与安装。即使挂了科学上网&#xff0c;国外的服务器下载速度也还是超级慢。 在网上找了各种解决办法后&#xff0c;终于找到一个快速下载安装的办法。 2 安装器下载 阿里源、清华源都没有Windows的安装器了&#xff0c;在腾讯…

IPv4地址细讲

文章目录一、IPv4地址简介二、IPv4地址的表示方法点分十进制记法三、IP地址的分类四、特殊IPv4地址&#xff1a;全 “0” 和全 “1”五、常用的三类IP地址使用范围六、五类IP地址的范围一、IPv4地址简介 IPv4地址分5类&#xff0c;每一类地址都由固定长度的字段组成&#xff1…

软件项目管理简答题复习(1)

1.项目&#xff1a;创造唯一的产品&#xff0c;唯一的服务临时性的努力 2.项目特征&#xff1a;不可见性&#xff0c;复杂性&#xff0c;一致性&#xff0c;变更性&#xff0c;特殊性 3.项目和日常活动的区别&#xff1f; 项目具有特殊性&#xff0c;负责人是项目经理&#…

软件项目管理计算题复习(1)

软件项目管理计算题复习&#xff08;1&#xff09; 1.关键路径&#xff1a;决定项目最早完成的一系列的活动。网络图中最长的路&#xff0c;最少的时差&#xff0c;总是差为0&#xff0c;也是关键路径。 2.最短路径也是最短工期 3.总时差&#xff1a;最晚开始-最早开始最晚结…

激光共聚焦显微镜在材料生产领域中的应用

在材料生产领域中&#xff0c;如需要分析金属材料/部件粗糙度的时候&#xff0c;不管是使用原子力显微镜还是台阶仪&#xff0c;都没有办法同时兼顾分辨率、扫描区域以及扫描速度。而基于激光共聚焦显微测量技术的共聚焦激光扫描显微镜&#xff0c;配备了真彩相机并提供还原的3…

NVIDIA CUDA初级教程视频学习笔记1

周斌老师 课程链接&#xff1a; 目录第一课内容生态环境第一课 CPU体系架构的概述什么是CPU指令存储器架构CPU内部的并行性第一课 预修课程&#xff1a; Cuda c programming guide 参考内容 1,2&#xff0c;3查找一下。 内容 CPU体系架构概述 并行程序设计概述 CUDA开发环境…

二叉树——二叉搜索树的最近公共祖先

二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#…

design\project\学习 OAuth 读书笔记(一)

OAuth&#xff08;一&#xff09; 原文链接&#xff1a;OAuth 2.0 tutorial | OAuth flows 目录OAuth&#xff08;一&#xff09;应用场景分析问题1&#xff1a;代表用户授予有限访问权限OAuth 代表用户授权问题2&#xff1a;允许第三方应用程序有限的访问API&#xff08;服务…