c语言结构体字节对齐的实现方法

目录
  • 1.什么是字节对齐
  • 2.为什么要有字节对齐
  • 3.手动设置对齐
  • 4.结构体比较方法

1.什么是字节对齐

在c语言的结构体里面一般会按照某种规则去进行字节对齐。

我们先看一段代码:

struct st1
{
 char name;
 double age;
 char sex;
};
//32位下 sizeof(struct st1) = 16
//64位下 sizeof(struct st1) = 24
struct st2
{
 char a;
 char b;
 char c;
};
//32位和64位下, sizeof(struct st2)都是3个字节

从以上结果可以看出,结构体st1在32位下是按照4个字节来对齐的,在64位下则是按照8个字节来对齐的,结构体st2则不管32位还是64位则都是按照1个字节对齐的。
那么我们可以总结出对齐规则如下:

  • 在所有结构体成员的字节长度都没有超出操作系统基本字节单位(32位操作系统是4,64位操作系统是8)的情况下,按照结构体中字节最大的变量长度来对齐;
  • 若结构体中某个变量字节超出操作系统基本字节单位,那么就按照系统字节单位来对齐。

注意:并不是32位就直接按照4个字节对齐,64位按照8个字节对齐。

2.为什么要有字节对齐

首先普及一点小知识,cpu一次能读取多少内存要看数据总线是多少位,如果是16位,则一次只能读取2个字节,如果是32位,则可以读取4个字节,并且cpu不能跨内存区间访问。

假设有这样一个结构体如下:

struct st3
{
    char a;
    int b;
};
//那么根据我们第1节所说的规则,在32位系统下,它就应该是8个字节的。

假设地址空间是类似下面这样的:

在没有字节对齐的情况下,变量a就是占用了0x00000001这一个字节,而变量b则是占用了0x00000002~0x000000005这四个字节,那么cpu如果想从内存中读取变量b,首先要从变量b的开始地址0x00000002读到0x0000004,然后再读取一次0x00000005这个字节,相当于读一个int,cpu从内存读取了两次。

而如果进行字节对齐的话,变量a还是占用了0x00000001这一个字节,而变量b则是占用了0x00000005~0x00000008这四个字节,那么cpu要读取变量b的话,就直接一次性从0x00000005读到0x00000008,就一次全部读取出来了。

所以说,字节对齐的根本原因其实在于cpu读取内存的效率问题,对齐以后,cpu读取内存的效率会更快。但是这里有个问题,就是对齐的时候0x00000002~0x00000004这三个字节是浪费的,所以字节对齐实际上也有那么点以空间换时间的意思,具体写代码的时候怎么选择,其实是看个人的。

3.手动设置对齐

什么情况下需要手动设置对齐:

  • 设计不同CPU下的通信协议,比如两台服务器之间进行网络通信,共用一个结构体时,需要手动设置对齐规则,确保两边结构体长度一直;
  • 编写硬件驱动程序时寄存器的结构;

手动设置对齐方式有两种:

代码里添加预编译标识:

//用法如下
#pragma pack(n)//表示它后面的代码都按照n个字节对齐
struct st3
{
    char a;
    int b;
};
#pragma pack()//取消按照n个字节对齐,是对#pragma pack(n)的一个反向操作
//这里计算sizeof(st3)=5

上面这两行其实就类似于开车的时候,走到某一段路的时候,发现一个限速60公里的指示牌,过了那一段路以后,又会有解除限速60公里的指示牌。

定义结构体时:

//用法如下
struct bbb
{
   char a;
   int b;
}__attribute__((packed));//直接按照实际占用字节来对齐,其实就是相当于按照1个字节对齐了
//这里计算sizeof(st3)=5

4.结构体比较方法

可以使用内存比较函数memcpy进行结构体比较,但因为结构体对齐可能会有填充位不一致的情况,此时需要注意:

  • 设置为1个字节对齐,使它没有空位;
  • 事先对结构体进行初始化;
memcpy(char *dest, const char* src, int len); //头文件#include<string.h>

到此这篇关于c语言结构体字节对齐的实现方法的文章就介绍到这了,更多相关c语言结构体字节对齐内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言新手练习之多维数组、结构体及函数

    1887 颜色精简 题目: 有一个颜色集合,里面有若干个颜色值(RBG系统表示).现在有若干个颜色值需要映射到集合中的某个值.具体的映射方法是找到集合中和它的颜色距离最小的进行映射.在RGB颜色系统中,颜色用 (R,G,B) 三元组表示,R,G,B是0到255之间的整数.两个颜色之间的距离定义如下:假设给定两个颜色的三元组分别是 (Ra,Ga,Ba) 和 (Rb,Gb,Bb) ,那么他们之间的距离 输入: 先输入一个整数n(1<=n<=20),表示集合中有多少种颜色. 接下来n行给出集合中的颜

  • C语言中结构体和共用体实例教程

    目录 一.实验目的 二.实验内容 三.实验记录 3.1 候选人选票统计 3.2 print函数 3.3 链表 总结 一.实验目的 掌握结构体类型变量的定义和使用: 掌握结构体类型数组的概念和应用: 掌握链表的概念,初步学会对链表进行操作: 掌握共用体的概念与使用: 掌握指向结构体变量的指针. 掌握指向结构体数组的指针的应用. 二.实验内容 编写下列程序,然后上机调试运行. 对候选人得票的统计程序.设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果. 编写一个函数print,

  • C语言结构体计算内存占用问题解析

        c语言中结构体使用是非常广泛的,但是结构体有一个问题,就是如果开头的字段属性是字符类型(char),紧跟着的是其他类型,比如整型.长整型.双精度.浮点型,这时候结构体的大小会发生改变,下面给出一个示例: #include <stdio.h> struct person{ char sex; int age; char name[8]; }; int main() { printf("sizeof(person) = %d\n",sizeof(struct perso

  • C语言结构体简单入门讲解

    结构体 定义:用于存储不同的数据类型,存储在同一块内存空间里面 关键字 struct 标签 结构体名称 成员 例如: struct student { char name[20]: char sex; int age; float grade; }: 结构体后面不要忘记加分号 结构体至少需要一个标签,证明身份 结构体的使用 .访问指针 →访问 #include <stdio.h> #include <string.h> struct student { char name[20];

  • C语言结构体的具体使用方法

    目录 初识C语言结构体 1.为什么要有结构体 2.结构体的定义 2.1结构体类型的定义 2.2定义结构体普通变量及访问 2.3定义结构体指针变量及访问 初识C语言结构体 1.为什么要有结构体 (1)之前int.char等类型描述的结构体非常单一,只可描述一种类型. (2)数组也是描述同一类型的集合,只可描述一种类型. (3)而结构体使得C语言可以描述复杂类型,比如学生类型( 包含学生的名字.年龄.性别.电话号等信息). 结构体和数组的区别: ·结构体:用来描述相同/不同数据元素类型的集合. ·数

  • C语言中结构体、联合体的成员内存对齐情况

    前言 最近项目进行中,遇到一个小问题,在数据协议传输过程中,我为了方便解析,就定义了一个结构体,在数据的指针传入函数的时候,我用定义好的结构体进行强制转化,没想到一直解析失败,调试很久,终于反应过来,在用结构体指针对数据强制转换时,定义结构体我没有注意到数据对齐,因为在底层实现中,我传入的数据buffer是排列整齐的,而强制转化的结构体格式中,我定义的时候没有使用__attribute__((__packed__))或者__packed强制数据对齐,导致结构体成员真实排列会按照成员中最大的变量的

  • C 语言结构体的使用方法

    目录 C 语言结构体使用 1. 结构体的声明和定义 1.1 介绍 1.2定义的几种类型 2. 结构体初始化 3. 结构体成员访问 3.1 成员介绍 4. 结构体传参 C 语言结构体使用 1. 结构体的声明和定义 1.1 介绍 我们知道数组是同种类型值的集合,而结构就是可以将不同类型的值放在一起. 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. 结构的成员可以是标量.数组.指针,甚至是其他结构体. 如我们可以将一个学生的一些属性放在一起 struct stu//定义一

  • C语言自定义类型详解(结构体、枚举、联合体和位段)

    目录 前言 一.结构体 1.结构体类型的声明 2.结构体的自引用 3.结构体变量的定义和初始化 4.结构体内存对齐 5.结构体传参 二.位段 1.位段的定义 2.位段的内存分配 3.位段的应用 三.枚举 1.枚举类型的定义 2.枚举的优点 3.枚举的使用 四.联合体(共用体) 1.联合体的定义 2.联合体的特点 3.联合体的大小计算 总结 前言 一.结构体 1.结构体类型的声明 当我们想要描述一个复杂变量--学生,可以这样声明. ✒️代码展示: struct Stu { char name[20

  • C语言入门篇--初识结构体

    目录 1.为什么要有结构体 2.结构体的定义 2.1结构体类型的定义 2.2定义结构体普通变量及访问 2.3定义结构体指针变量及访问 1.为什么要有结构体 (1)之前int.char等类型描述的结构体非常单一,只可描述一种类型. (2)数组也是描述同一类型的集合,只可描述一种类型. (3)而结构体使得C语言可以描述复杂类型,比如学生类型( 包含学生的名字.年龄.性别.电话号等信息). 结构体和数组的区别: 结构体:用来描述相同/不同数据元素类型的集合. 数组:用来描述具有相同数据元素类型的集合.

  • C语言中结构体与内存对齐实例解析

    1.结构体类型 C语言中的2种类型:原生类型和自定义类型,结构体类型是一种自定义类型. 2.结构体使用时先定义结构体类型再用类型定义变量 -> 结构体定义时需要先定义结构体类型,然后再用类型来定义变量. -> 也可以在定义结构体类型的同时定义结构体变量. // 定义类型 struct people { char name[20]; int age; }; // 定义类型的同时定义变量. struct student { char name[20]; int age; }s1; // 将类型st

  • C语言结构体内存的对齐知识详解

    前言 在前面的章节中,我们谈到了C语言中整数以及浮点数的储存 今天,我们来谈一谈一些关于结构体内存的知识. 我们先来看一个例子: struct S1 { char c1; int i; char c2; }; 大家来猜猜这个结构体S1的内存是多少? 相信会有人给出 6 的结果,他们或许是这样想的,两个 char 类型分别为一个字节,一个 int 类型又为4个字节,加起来刚好为6个 但是 结果真是如此吗? 我们来看看运行结果: 为什么呢,接下来我们就引出正文. 一.结构体内存对齐规则 首先,正如引

  • C语言结构体指针案例解析

    写结构体指针前,先说一下 . 号和 -> 的区别 记得当初刚学C语言的时候,搞不清结构体的 . 号和 -> ,经常混淆二者的使用. 那么在C语言中 . 号是成员访问运算符,当我们需要访问结构的成员的时候,就会使用到它 而当我们需要使用结构体指针来访问结构成员的时候,就得使用->运算符了. 结构体指针栗子: ​#include<stdio.h> #include<string.h> typedef struct student{ int id; char name[

  • C语言结构体版学生成绩管理系统

    本文实例为大家分享了C语言实现学生成绩管理系统的具体代码,供大家参考,具体内容如下 结构体版的学生成绩管理系统 主要功能有 按1 输入学生信息 按2 输出学生信息 按3 查询学生信息 按4 修改学生信息 按5 删除学生信息 按6 插入学生信息 按7 排序总成绩信息 学生信息主要有姓名,班级,学号,C语言成绩,高数成绩,大学英语成绩,控制台界面输出格式有点不美观. #include<stdio.h> #include<string.h> struct student { char n

  • C语言自定义数据类型的结构体、枚举和联合详解

    结构体基础知识 首先结构体的出现是因为我们使用C语言的基本类型无法满足我们的需求,比如我们要描述一本书,就需要书名,作者,价格,出版社等等一系列的属性,无疑C语言的基本数据类型无法解决,所以就出现了最重要的自定义数据类型,结构体. 首先我们创建一个书的结构体类型来认识一下 struct Book { char name[20]; char author[20]; int price; }; 首先是struct是结构体关键字,用来告诉编译器你这里声明的是一个结构体类型而不是其他的东西,然后是Boo

  • C语言结构体占用内存深入讲解

    前言 前几天有个小朋友问了我一下,关于C语言结构体占用空间的问题.觉得以后会对小可爱有点帮助,就打算先写一下. struct Test { int a; char b; int c; } test; 理论上,结构体中的各个成员在内存中应该是连续储存的,就像数组里面的元素一样.事实上,也确实是这个样子的,不过和我们想象的有点不一样. 按照我们最初的想法,变量test所占的内存为 4 + 1 + 4 = 9. 但是我们写一个小代码验证一下发现和我们想的不一样. 它的内存为12.因为 int类型是4个

  • C语言使用四种方法初始化结构体

    什么是结构体 在实际问题中,一组数据往往有很多种不同的数据类型.例如,登记学生的信息,可能需要用到 char型的姓名,int型或 char型的学号,int型的年龄,char型的性别,float型的成绩.又例如,对于记录一本书,需要 char型的书名,char型的作者名,float型的价格.在这些情况下,使用简单的基本数据类型甚至是数组都是很困难的.而结构体(类似Pascal中的"记录"),则可以有效的解决这个问题.结构体本质上还是一种数据类型,但它可以包括若干个"成员&quo

随机推荐