c/c++--字节对齐(byte alignment)

news2024/7/6 17:53:50

1. 默认字节对齐

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

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

2. 为什么存在字节对齐

2.1 了解 CPU 一次读取内存数

CPU 一次能读取多少内存要看数据总线是多少位

  • 如果是16位,则一次只能读取 2 个字节
  • 如果是32位,则可以读取 4 个字节,并且 CPU 不能跨内存区间访问

例子:

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

struct st3
{
    char a;
    int b;
};
//在32位系统下,它就应该是8个字节的。

假设地址空间是类似下面这样的:
在这里插入图片描述

  • 在没有字节对齐的情况下

    1. 变量 a 就是占用了 0x00000001 这一个字节,而变量b则是占用了 0x00000002~0x000000005 这四个字节
    2. 此时 cpu 如果想从内存中读取变量 b,首先要从变量 b 的开始地址 0x00000002读到 0x0000004,然后再读取一次 0x00000005 这个字节,相当于读一个 int,cpu 从内存读取了两次
  • 如果进行字节对齐的话

    1. 变量 a 还是占用了 0x00000001 这一个字节,而变量 b 则是占用了 0x00000005~0x00000008 这四个字节
    2. 此时 cpu 要读取变量 b 的话,就直接一次性从 0x00000005 读到 0x00000008 ,就一次全部读取出来了。

总结:

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

3. 编码时手动设置对齐

两种。

3.1 代码里添加预编译标识 pragma pack(n)

3.1.1 用法

  • 使用预编译指令 #pragma pack (n) 来告诉编译器,使用我们指定的对齐值来取代缺省的。
  • 对齐的算法: 随编译器变化
//用法如下
#pragma pack(n)//表示它后面的代码都按照n个字节对齐
struct st3
{
    char a;
    int b;
};
#pragma pack()//取消按照n个字节对齐,是对#pragma pack(n)的一个反向操作

3.1.2 例子

#include <stdio.h>

#pragma pack(1)//表示它后面的代码都按照n个字节对齐
struct st3
{
    char a;
    int b;
};
#pragma pack()//取消按照n个字节对齐,是对#pragma pack(n)的一个反向操作

#pragma pack(2)//表示它后面的代码都按照n个字节对齐
struct st4
{
    char a;
    int b;
};
#pragma pack()//取消按照n个字节对齐,是对#pragma pack(n)的一个反向操作

int main()
{
   	
    printf("%d\n",sizeof(struct st3) );
    printf("%d\n",sizeof(struct st4) );
	
   	return 0;
}

在这里插入图片描述

3.2 定义结构体时指定__attribute__((packed))

3.2.1 用法

  • __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。这个功能是跟操作系统没关系跟编译器有关.
//用法如下
struct bbb
{
   char a;
   int b;
}__attribute__((packed));//直接按照实际占用字节来对齐,其实就是相当于按照1个字节对齐了
//这里计算sizeof(st3)=5

3.2.2 例子

#include <stdio.h>

struct st3
{
   char a;
   int b;
}__attribute__((packed));

struct __attribute__((packed)) st4
{
	int b;
	char a;
};

int main()
{
   	
    printf("%d\n",sizeof(struct st3) );
    printf("%d\n",sizeof(struct st4) );
	
   	return 0;
}

在这里插入图片描述

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

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

相关文章

MQTT C库下载

方法一、从Eclipse paho下载 https://eclipse.dev/paho/index.php?pagedownloads.php 方法二&#xff0c;从MQTT官网下载 https://mqtt.org/software/ https://os.mbed.com/teams/mqtt/code/MQTTPacket/ MQTTPacket源码和paho下载的差不多 方法三、从Keil5 包管理工具…

刷新页面,时间展示错误

当我们刷新页面之前时间是正常展示的&#xff0c;在刷新页面之后&#xff0c;时间也在展示&#xff0c;只不过时间错误。 刷新之前 刷新之后&#xff08;系统原因暂时拿不到数据&#xff09;&#xff1a;用同一图代替&#xff0c;颜色是灰色 明显可以看到时间颜色发生了变化&a…

C++智能指针(二)——weak_ptr初探

文章目录 1. shared_ptr 存在的问题2. 使用weak_ptr2.1 初始化 weak_ptr2.2 访问数据 1. shared_ptr 存在的问题 与 shared_ptr 的引入要解决普通指针存在的一些问题一样&#xff0c;weak_ptr 的引入&#xff0c;也是因为 shared_ptr 本身在某些情况下&#xff0c;存在一些问题…

android U广播详解(一)

概念介绍 进程队列 BroadcastQueueModernImpl 的设计围绕着为设备上的每个潜在进程维护一个单独的 BroadcastProcessQueue 实例。表明用于传送到特定进程的Pending {link BroadcastRecord} 条目队列。整个类都标记为 {code NotThreadSafe}&#xff0c;因为调用者有责任始终与…

Linux 用户层、内核层和MMU

一、Linux 用户层、内核层 在 Linux 中&#xff0c;所有设备都以文件的形式存放在/dev 目录下&#xff0c;都是通过文件的方式进行访问&#xff0c;设备节点是Linux 内核对设备的抽象&#xff0c;一个设备节点就是一个文件。应用程序通过一组标准化的调用执行访问设备&#xff…

SwiftUI 中如何实现文件导入和导出

文章目录 前言导入导出文件移动总结 前言 之前谈论了在 SwiftUI 中选择照片和视频的问题。今天我们将学习如何在 SwiftUI 视图中导入和导出文件。通过使用新的 fileImporter 和 fileExporter 视图修饰符&#xff0c;可以很方便实现这个功能。 导入 SwiftUI 框架提供了 fileI…

RAMday9

设置按键中断&#xff0c;按键1按下&#xff0c;LED亮&#xff0c;再按一次,灭&#xff1b;按键2按下&#xff0c;蜂鸣器响&#xff0c;再按一次&#xff0c;不响&#xff1b;按键3按下&#xff0c;风扇转,再按一次,风扇停 代码 do_irq.c #include "key.h" extern…

火狐浏览器页面翻译

打开扩展 扩展搜索tran 点击谷歌快译组件 设置翻译语言 安装完成后即可右键翻译页面

【数据库——MySQL(实战项目1)】(3)图书借阅系统——存储函数

目录 1. 简述2. 功能代码2.1 创建存储函数&#xff0c;根据图书编号查借阅人姓名&#xff0c;并调用该函数查询‘ **小邓在森林** ’已借未还的图书情况&#xff1b;2.2 创建存储函数&#xff0c;计算某借阅人还能借阅的图书数目&#xff0c;学生限额 5 本&#xff0c;教师限额…

两个连续变量乘积线性化——McCormick envelope近似

两个连续变量乘积的形式&#xff0c;可以进行近似线性化转化&#xff08;没有完全等价的线性化方法&#xff09;。要说明的是这是一种近似线性化&#xff0c;并不是完全等价&#xff0c;存在一定的误差。转化的方法是&#xff0c;McCormick envelope近似&#xff08;McCormick …

快速解决“找不到msvcr120.dll无法执行代码”问题,总结5解决方法

计算机已经成为我们生活和工作中不可或缺的一部分。然而&#xff0c;在使用计算机的过程中&#xff0c;我们常常会遇到各种问题&#xff0c;其中之一就是找不到msvcr120.dll文件。这个问题可能会可能导致计算机程序软件&#xff0c;游戏无法正常运行&#xff0c;影响到我们的工…

试图带你一文搞懂transformer注意力机制(Self-Attention)的本质

这篇文章主要想搞懂以下几个问题&#xff1a; 1、什么是自注意力&#xff08;Self-Attention&#xff09; 2、Q,K,V是什么 好了废话不多说&#xff0c;直接进入正题 Q,K,V分别代表query&#xff0c;key和value&#xff0c;这很容易让人联想到python的字典数据结构&#xff…

西安交大转子数据集故障诊断(Python代码,MSCNN结合LSTM结合注意力机制模型)

1.运行效果&#xff1a;西安交大转子数据集故障诊断&#xff08;Python代码&#xff0c;MSCNN结合LSTM结合注意力机制模型&#xff09;_哔哩哔哩_bilibili 2.环境库版本 如果库版本不一样&#xff0c; 一般也可以运行&#xff0c;这里展示我运行时候的库版本&#xff0c;是为了…

多线程 - 锁策略 CAS

常见的锁策略 此处谈到的锁策略,不局限于 Java,C,Python,数据库,操作系统……但凡是涉及到锁,都是可以应用到下列的锁策略的 乐观锁 vs 悲观锁 锁的实现者,预测接下来锁冲突(锁竞争,两个线程针对一个对象加锁,产生阻塞等待了)的概率是大,还是不大,根据这个冲突的概率,来接下…

30+程序员:如何成为工作领域专家丨IDCF

想要独立完成有一定复杂度的开发和维护工作&#xff0c;或者带领团队完成产品发布、项目交付&#xff1f;要成为研发经理、核心项目负责人&#xff1f; 但又苦于没有丰富的实战经验、或是有经验但是没有可以证明能力水平的认证。 在IT行业&#xff0c;年龄是一个敏感话题。特…

AI一体化运维监控方案助力医院监控体系信息化、智能化

智慧医院是现代医疗领域的新兴概念&#xff0c;是通过先进的物联网技术和新兴技术联合人工智能&#xff0c;实现一体化医院运维监控管理&#xff0c;旨在提升医院的安全性、运行效率和服务质量。 具体方案 1、 视频监控系统 医院可以安装视频监控摄像头&#xff0c;覆盖关键区…

vue-mixin

1.vue中&#xff0c;混入(mixin)是一种特殊的使用方式。一个混入对象可以包含任意的组件配置选项(data, props, components, watch,computed…)可以根据需求"封装"一些可复用的单元&#xff0c;并在使用时根据一定的策略合并到组件的选项中&#xff0c;使用时和组件自…

记录使用vant组件库的Popup的问题

使用过程中,需要实现点击遮罩层不关闭,智能点击关闭按钮或提交按钮才能关闭遮罩层,看了官网要使用close-on-click-overlay属性, 一开始的写法是错误的: close-on-click-overlayfalse 这个写法明显传递的是string, 而官网中明确要求要穿布尔值, 所以需要在前面加冒号 :clos…

【基础篇】三、Flink集群角色、系统架构以及作业提交流程

文章目录 1、集群角色2、部署模式3、Flink系统架构3.1 作业管理器&#xff08;JobManager&#xff09;3.2 任务管理器&#xff08;TaskManager&#xff09; 4、独立部署会话模式下的作业提交流程5、Yarn部署的应用模式下作业提交流程 1、集群角色 Flink提交作业和执行任务&…

04在命令行中使用Maven命令创建Maven版的Web工程,并将工程部署到服务器的步骤

创建Maven版的Web工程 使用命令生成Web工程 使用mvn archetype:generate命令生成Web工程时&#xff0c;需要使用一个专门生成Web工程骨架的archetype(参照官网看到它的用法) -D表示后面要附加命令的参数&#xff0c;字母D和后面的参数是紧挨着的&#xff0c;中间没有任何其它…