C语言----字节对齐

一:字节对齐的概念

        针对字节对齐,百度百科的解释如下:

        字节对齐是字节按照一定规则在空间上排列,字节(Byte)是计算机信息技术用于计量存储容量和传输容量的一种计量单位,一个字节等于8位二进制数,在UTF-8编码中,一个英文字符等于一个字节,字节按照一定规则在空间上排列就是字节对齐。

        上面就提到按照一定规则,那规则是什么,按什么规则去对齐,带着这个疑问往下走

二:为什么要字节对齐

        我们为什么要进行字节对齐,不对齐会有什么后果,在计算机中我们任何一个动作无非就是保证程序的正确性,提高程序的性能和可靠性。

        1,平台的硬要求,必须要字节对齐

        某些平台对特定类型的数据只能从特定地址开始存取,而不允许其在内存中任意存放。例如,Motorola 68000 处理器不允许16位的字存放在奇地址,否则会触发异常,因此在这种架构下编程必须保证字节对齐。

        2,提高程序的性能

        字节对齐如何能提高程序的性能?CPU内部有几个重要的部件决定了CPU一次能处理的字节和可访问的内存大小。寄存器,ALU和数据总线的位数,这些共同决定了CPU的字长,常见CPU的字长有4位,8位,16位,32位和64位。字长越多,则CPU内部硬件规模和造价越高。如果CPU字长是16位。它的寄存器和总线也是16位。那么它一次处理的数据长度就为2字节。

        当访问一个变量时,当该变量的地址为偶地址(即字变量的低字节在偶地址单元,高字节在奇地址单元),则需要一个总线周期访问该字变量;如果该字变量的地址为奇地址(即字变量的低字节在奇地址单元,高字节在偶地址单元),则需要用两个连续的总线周期才能访问该字变量,每个周期访问一个字节。

        字节对齐让CPU读取数据的效果高了,这就解释了为什么字节对齐能提高程序的性能。

        3,节省程序的内存

        下面我们以一个实际的例子来看看字节对齐如何节省内存

#include <stdio.h>
#include <stdlib.h>struct byte1
{char a;int b;short c;
};struct byte2
{char a;short c;int b;
};int main()
{// please write your code hereprintf("struct byte1 size:%d\n",sizeof(struct byte1));printf("struct byte2 size:%d\n",sizeof(struct byte2));
}

 可以看到,同样是存储一个char,一个int,一个short,结构体中顺序不一样,结构体的所占的空间也不一样。之所以出现上述结果,就是因为编译器要对数据成员在空间上进行对齐

三:字节对齐规则

1,基本类型对齐规则

基本类型包括char、int、float、double、short、long等基本数据类型。CPU位数不同所占的字节数也不一样,如下图所示

在这里插入图片描述

         对齐要求:起始地址为其长度的整数倍即可。如,int类型的变量起始地址要求为4的整数倍,char类型的变量只占一个字节,那起始地址放哪都行。

2,结构体对齐规则

1>每个数据成员的起始位置必须是自身大小的整数倍; 

2>结构体总大小必须是结构体成员中最大的对齐模数的整数倍;

3> 结构体包含数组时,按单个类型对齐方式;

4>共用体union取成员的最大内存,但包含在结构体内时,按union内部最大类型字节数的整数倍开始存储;

struct byte1
{char a;int b;short c;
};

结构体大小:12
解释:char占一个字节,int占四个字节,由于int的起始地址要在4的倍数上,char后边补齐3个字节,shor占两个字节,但是整个结构体大小要是最大的对齐模数的整数倍,即4的倍数,所以补两个字节,一共12个字节

struct byte2
{char a;short c;int b;
};

结构体大小:8

解释:char占一个字节,short占两个字节,由于short的起始地址要在2的倍数上,char后边补齐1个字节,int占四个字节,刚好在4的倍数上,所以总共8个字节

那结构体里嵌套结构体呢?

结构体包含另一个结构体成员,则被包含的结构体成员要从其原始结构体内部的最大对齐模数的整数倍地址开始存储(比如struct a里含有struct b,b中有char、double 、int 元素,那么b应该从8(double)的整数倍开始存储)

结构体嵌套共同体

结构体包含共用体成员,则该共用体成员要从其原始共用体内部成员中的最大对齐模数的整数倍地址开始存储

结构体最后包含0数组

struct byte2
{char a;short c;int b;double d[0];
};

结构体最后包含0数组,那0数组占空间吗?长度为0的数组的主要用途是为了满足需要可变长度的结构体,具体用法是在一个结构体的最后,申明一个长度为0的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量,数组名这个符号本身代表了一个不可修改的地址常量。

3,共同体对齐规则

共同体的内存除了取最大成员内存外,还要保证是所有成员类型size的最小公倍数。

union byte3
{char a;short c[5];int b;
};

 共同体byte3中最大成员就是short c[5],占10个字节,由于要保证是所有成员类型size的最小公倍数,即4个倍数,所以是12

4,存在#pragma pack宏的对齐规则

#pragma pack(n)//编译器将按照n个字节对齐

#pragma pack()//取消自定义字节对齐方式

******对齐规则******

结构体、联合、类的结构成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和自身对齐模数中最小的那个。

结构体的大小是#pragma pack指定的数值的整数倍。

#pragma pack(4)
typedef struct 
{int age;char name[0];double a;
} Person;
#pragma pack();//结束#pragma pack(4)对齐。  如果没有结束,aa也按照#pragma pack(4)对齐typedef struct 
{double age;Person k;
} aa;int m=sizeof(Person); // m=12, 按照4字节对齐
int n=sizeof(aa); // n=24,  按照8字节对齐        按照#pragma pack(4)对齐的话,n=20

5,位域字节对齐规则

“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。使用位域的主要目的是压缩存储。

位域列表的形式为: 类型说明符 位域名:位域长度(单位:位 bite)

如:struct bs
      {
           int a:8;
           int b:2;
           int c:6;
       } data;
其中位域a占8位,位域b占2位,位域c占6位。

位域说明:

1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域

2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节(8位)的长度,也就是说不能超过8位二进位。
3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如: int :2
 

位域对齐规则

1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

3) 如果相邻的位域字段的类型不同从新的存储单元开始,偏移量为其类型大小的整数倍,即不压缩;(各编译器的具体实现有差异,VC6采取不压缩方式,Dev-  

     C++采取压缩方式)

4) 如果位域字段之间穿插着非位域字段,则不进行压缩

5) 整个结构体的总大小为最宽基本类型成员大小的整数倍


例题:

(1)typedef struct  AA
{
       unsigned int b1:5;
       unsigned int b2:5;
       unsigned int b3:5;
       unsigned int b4:5;
       unsigned int b5:5;
}AA;

sizeof(AA)= 4 

【解析】参考规则 1)。由于相邻成员类型相同,unsigned int为 4 个字节,b1占5位,b2加上b1的位数之和为10位,不超过4字节,因此b2接着b1继续存储;

      同理b3、b4、b5的类型相同,位数之和不超过4字节,因此接着b2继续存储,总位数为25位。

      由于结构体的大小是最宽类型成员的整数倍,因此25位之后的补0,直到补满4字节。

(2)typedef struct  AA
{
       unsigned int b1:5;
       unsigned int b2:5;
       unsigned int b3:5;
       unsigned int b4:5;
       unsigned int b5:5;
       unsigned int b6:5;
       unsigned int b7:5;
}AA;
   sizeof(AA)= 8 

【解析】参考规则 1) 和规则 2) 。由于相邻成员类型相同,unsigned int为 4 个字节(32位),当存储到 b7 时,b7和b6之前的位数相加超过4字节,

因此b7从新的存储单元开始存储。

即b1~b6 存储在 第0~29位,第30、31位补0,b7从下一个 4字节存储单元 开始存储5位,剩下的补0。

 (3)struct test1

{

char a:1;

char :2;

long b:3;

char c:2;

};

 sizeof(test1)= 12

【解析】 

char a:1; //用一个字节去存储

char :2;  //空域。因为与前面的a的类型相同,而两个位域的位宽相加仍然少于8位,所以依然用1个字节表示

long b:3; //long类型的位宽是4个字节,与前面的char类型不同,所以b与a之间偏移4个字节,它们之间自动补充3个字节 

char c:2; //因为c与b又不同型,以test1中的最长的long类型的位宽进行偏移,所以虽然char只用1个字节就够了,但依然要占4个字节。

结构体总长以最长的类型位宽做为偏移量,最长的是long型,占4位,所以不同类型之间应该是4个字节的偏移,即test1应该是4字节的整数倍。 

总共是12字节。

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

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

相关文章

ChatGPT在工作中的七种用途

1. 用 ChatGPT 替代谷歌搜索引擎 工作时&#xff0c;你一天会访问几次搜索引擎&#xff1f;有了 ChatGPT&#xff0c;使用搜索引擎的频率可能大大下降。 据报道&#xff0c;谷歌这样的搜索引擎巨头&#xff0c;实际上很担心用户最终会把自己的搜索工具换成 ChatGPT。该公司针对…

首批获得金融级行业云平台认证,天翼云深耕行业云

云计算下半场看什么&#xff1f; 无疑是金融、政务、制造等传统政企用户的上云与用云。随着数字经济发展和产业数字化的提速&#xff0c;上云已是政企用户推动其数字化转型不断深入的重要抓手&#xff0c;成为不可阻挡的趋势。 与互联网用户相比&#xff0c;政企用户上云极为…

数据库的约束 详解

一、约束的概述 1.概念:约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 2&#xff0e;目的:保证数据库中数据的正确、有效性和完整性。 3.分类: 约束描述关键字非空约束限制该字段的数据不能为nullNOT NULL唯一约束保证该字段的所有数据都是唯一、不…

Mybatis实现JsonObject对象与JSON之间交互

项目中使用PostGresql数据库进行数据存储&#xff0c;表中某字段为Json类型&#xff0c;用于存储Json格式数据。PG数据库能够直接存储Json算是一大特色&#xff0c;很多特定情境下使用直接存储Json字段数据能够大量节省开发时间&#xff0c;提高后台数据查询和转换效率。 1、基…

微信小程序如何引入Iconfont

在小程序中引入 Iconfont 可以通过以下步骤进行操作&#xff1a; 打开 Iconfont 网站&#xff08;https://www.iconfont.cn/&#xff09;并登录账号&#xff0c;创建一个项目并添加所需的图标到项目中。 在项目中选中需要使用的图标&#xff0c;点击右上角的 “下载代码” 按钮…

Spring Boot 中自动装配机制的原理

问题描述 自动装配&#xff0c;简单来说就是自动把第三方组件的 Bean 装载到 Spring IOC 器里面&#xff0c;不需 要开发人员再去写 Bean 的装配配置。 在 Spring Boot 应用里面&#xff0c;只需要在启动类加上SpringBootApplication 注解就可以实现自动装配。 SpringBootAppli…

【机器学习】对 MLOps 的友好的介绍(MLOps1)

一、说明 我对 MLOps 感兴趣已经有一段时间了。我第一次从机器学习工程师那里了解到它&#xff0c;由于我当时还是一名博士生&#xff0c;我并不知道它的存在。然而&#xff0c;我的好奇心被激起了&#xff0c;我开始了解它。回想起来&#xff0c;我很后悔没有早点了解它&#…

云原生应用里的服务发现

服务定义&#xff1a; 服务定义是声明给定服务如何被消费者/客户端使用的方式。在建立服务之间的同步通信通道之前&#xff0c;它会与消费者共享。 同步通信中的服务定义&#xff1a; 微服务可以将其服务定义发布到服务注册表&#xff08;或由微服务所有者手动发布&#xff09;…

视频添加字幕

1、依靠ffmpeg 命令 package zimu;import java.io.IOException;public class TestSrt {public static void main(String[] args) {String videoFile "/test/test1.mp4";String subtitleFile "/test/test1.SRT";String outputFile "/test/testout13…

Redis入门

0目录 1.Redis入门 2.Redis定义&#xff1b;特点及数据类型 3.Value为List类型 4.Value值类型为Set 5.Value值类型为Hash 6.Value值类型为Zset 1.Redis入门 Redis入门 解压包&#xff0c;运行redis-server.exe 安装可视化软件测试链接 命名测试链接 点击确定 2.Redis…

ResNet50卷积神经网络输出数据形参分析-笔记

ResNet50卷积神经网络输出数据形参分析-笔记 ResNet50包含多个模块&#xff0c;其中第2到第5个模块分别包含3、4、6、3个残差块 5049个卷积&#xff08;3463)*31和一个全连接层 分析结果为&#xff1a; 输入数据形状:[10, 3, 224, 224] 最后输出结果&#xff1a;linear_0 [10,…

java使用openOffice将excel转换pdf时,将所有列显示在一页

1.接上文&#xff0c;格式转换的基础问题已解决&#xff0c;但还有些细节问题需要单独处理&#xff0c;如excel转换至pdf时&#xff0c;如何将所有列显示在一页的问题&#xff0c;此问题大家都有遇到&#xff0c;解决方案也比较多&#xff0c;我也尝试过重写某类&#xff0c;来…

Java基础面试题1

Java基础面试题 一、面向对象和集合专题 1. 面向对象和面向过程的区别 面向过程&#xff1a;是分析解决问题的步骤&#xff0c;然后用函数把这些步骤一步一步地实现&#xff0c;然后在使用的时候一一调用则可。性能较高&#xff0c;所以单片机、嵌入式开发等一般采用面向过程…

Stable diffusion 三大基础脚本 提示词矩阵,载入提示词,XYZ图表讲解

目录 0.本章讲解 1.提示词矩阵(prompt matrix) 1.2.提示词矩阵功能选项 1.2.1.把可变部分放在提示词文本的开头 1.2.2.为每张图片使用不同随机种子 1.2.3.选择提示词 1.2.4.选择分割符 1.2.5.宫格图边框&#xff08;像素&#xff09; 2.从文本框或文件载入提示词(Pro…

获取k8s scale资源对象的命令

kubectl get --raw /apis/<apiGroup>/<apiVersion>/namespaces/<namespaceName>/<resourceKind>/<resourceName>/scale 说明&#xff1a;scale资源对象用来水平扩展k8s资源对象的副本数&#xff0c;它是作为一种k8s资源对象的子资源存在&#xf…

STM32F103——基础篇

目录 1、寄存器基础知识 2、STM32F103系统架构 2.1 Cortex M3 内核&芯片 2.2 STM32F103系统架构 3、存储器映射 4、寄存器映射 4.1 寄存器描述解读 4.2 寄存器映射举例 4.3 寄存器地址计算 4.4 stm32f103xe.h 寄存器映射 1、寄存器基础知识 概念&#xff1a;寄存…

谈谈对Android音视频开发的探究

在日常生活中&#xff0c;视频类应用占据了我们越来越多的时间&#xff0c;各大公司也纷纷杀入这个战场&#xff0c;不管是抖音、快手等短视频类型&#xff0c;虎牙、斗鱼等直播类型&#xff0c;腾讯视频、爱奇艺、优酷等长视频类型&#xff0c;还是Vue、美拍等视频编辑美颜类型…

局域网部署,用WorkPlus视频会议保密又安全

用户采用私有化部署视频会议软件的情况主要有以下几种因素&#xff1a; 1. 针对机密性高的会议&#xff1a;如果有涉及高度机密的商业谈判或敏感信息交流等重要会议&#xff0c;政府、军工、企业等用户会选择局域网内部署视频会议软件&#xff0c;以保证信息安全。 2. 频繁进…

Tailwind CSS:简洁高效的工具,提升前端开发体验

112. Tailwind CSS&#xff1a;简洁高效的工具&#xff0c;提升前端开发体验 1. 什么是Tailwind CSS&#xff1f; Tailwind CSS是由Adam Wathan、Jonathan Reinink、David Hemphill和Steve Schoger等人共同创建的一种现代CSS框架。与传统的CSS框架不同&#xff0c;Tailwind CS…

AtcoderABC228场

A - On and OffA - On and Off 题目大意 一个人每天在指定的时间点打开房间的灯&#xff0c;并在另一个时间点关闭灯。问题是确定在给定的时间点&#xff0c;灯是否亮着。 思路分析 注意时间24小时制&#xff0c;同一天和隔夜两种情况 确定给定的时间点是否在灯亮的时间范围…