杂谈c语言——3.内存对齐

news2024/11/26 15:40:16

先看两个例子:

typedef struct S {
	int a;
	double b;
	char c;
}S;

typedef struct B {
	int a;
	char b;
	double c;
}B;


int main() {

	printf("S : %d\n", sizeof(S));
	printf("B : %d\n", sizeof(B));

	return 0;
}

结果为:

S:24;

B:16: 

可见不同,简单来说就是按照成员的定义顺序,依次为其分配内存,分配内存的起始偏移位置应该是选定对齐数的整数倍,最后结构体变量所占大小应该是成员最大对齐数的整数倍。 

1.对齐原则 

 内存对⻬规则

• 第⼀个成员在与结构体偏移量为0的地址处。

• 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处

• 注意:对⻬数 = 编译器默认的⼀个对⻬数 与 该成员⼤⼩的较⼩值。

• VS中默认的对⻬数为8

• 结构体总⼤⼩为:最⼤对⻬数(所有变量类型最⼤者与默认对⻬参数取最⼩)的整数倍

• 如果嵌套了结构体的情况,嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处,结构体的整体⼤⼩ 就是所有最⼤对⻬数(含嵌套结构体的对⻬数)的整数倍。

 

举例证明

//练习1.
struct A {
	char c;
	int i;
	char b;
};
 
int main(){
    printf("%d\n",sizeof(struct A));
    return 0;
    }

   结构体成员变量分配内存的详细过程:

        1.首先:char c为第一个成员变量,遵循第一条规则,char c从偏移量0开始,占1个字节,指针指向下一个偏移地址1

        2.接下来存放int i, 但偏移地址 “1” 并不是对齐数4的整数倍

对齐数4来自(对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。)规则2,成员变量2是int类型,大小为4字节,在VS中,编译器默认对齐数为8,8与4的较小值为4,所以成员变量2的对齐数为4

那么指针需要移动到对齐数4的整数倍,即偏移量4地址处,开始存放int i 占4个字节,且偏移量1~3为空闲区,浪费了。

        3.接下来指针指向了偏移地址9,第三个成员变量char b的对齐数是1,偏移9是对齐数1的整数倍,符合条件,存放char b,占一字节,指针指向偏移10地址,由第三条规则可知,. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍,struct A最大对齐数是int i的对齐数4,那么现偏移10并不是对齐数4的整数倍,指针继续向下寻找符合条件的偏移地址,最后指针指向偏移12,12是4的整数倍,符合规则,那么偏移结束。

        结果共占12字节,内存中浪费了6个字节。

                           

 

 

 

2.强化训练

struct S3
{
	double d;
	char c;
	int i;
};
 
 
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
 
int main(){
    printf("%d\n", sizeof(struct S4));
    return 0;
    }
 

由对齐原则可知sizeof(s3)=16;

计算sizeof(s4)

 练习4.结构体内存分配过程:

   1.首先:char c1为第一个成员变量,遵循第一条规则,char c从偏移量0开始,占1个字节,指针指向下一个偏移地址1

   2.其次,第二个成员变量为结构体S3,说明是嵌套结构体,通过刚才对S3的结构体大小可知是16字节,且S3中最大对齐数为8,通过规则4可知,现指针指向的偏移地址1并不是对齐数8的整数倍,所以指针需要向后跳转,直到指针指向偏移量为8的地址,才符合要求,开始存放struct S3成员变量,共16字节

    3.最后,指针指向偏移量为24的地址处,最后一个成员变量为double d,d的对齐数为8,偏移地址“24”是对齐数8的整数倍,所以开始存放double d,占8字节。

        现在指针指向了偏移量为32的地址,32是整个结构体最大对齐数8的整数倍,偏移结束,结构体S4共占32字节,浪费了7个字节(偏移地址1~7)。
 

 

3.内存对齐的原因 

 1. 不是所有的硬件平台都支持随意地址访问,有些硬件平台cpu只能从指定地址处读取指定大小的数据,减少了异常抛出。

 

 

!!!!!!!!!!!

第一个因为内存对齐,虽然ch只有1字节,但浪费3个字节 可以保证只读取到ch (不读到i)

第二个因为内存不对齐,会访问到ch和i的前3个字节的内容。会出问题

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

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

相关文章

【Qt】项目代码

main.cpp文件 argc:命令行参数个数。*argv[ ]:每一个命令行参数的内容。main的形参就是命令行参数。QApplication a(argc, argv) 编写一个Qt的图形化界面程序,一定需要QApplication对象。 widget w; 在创建项目的时候,勾选widg…

AI岗位平均月薪已经超过4.6万,程序员该如何抓住这个机遇?

前言 自从ChatGPT横空出世以来,市场上一直用“iPhone时刻”、“划时代”、“工业革命”等词汇来形容AI领域的飞速进展。如今,随着AI大模型的竞争日益激烈,这个领域正在以前所未有的速度向前发展。 AI大模型的革命性突破 OpenAI最新推出的G…

Linux--网络层IP

IP协议 IP协议,全称Internet Protocol(互联网协议),是TCP/IP协议族中的核心协议之一,用于在互联网络上进行数据的传输。IP协议的主要功能是确保数据从一个网络节点(如计算机、服务器、路由器等&#xff09…

【C++第11章】Vector

【C第11章】Vector vector介绍🧐 vector是表示可变大小数组的序列容器,它类似于数组,但大小可以动态改变,并且大小会被容器自动处理。本质上说,vector使用动态分配数组来存储元素,为了减少扩容代价&#x…

音频剪辑软件哪个好用?音乐制作必备的6款音频剪辑工具

在这个充满声音的世界里,音乐和音频不仅仅是艺术表达的一种形式,更是情感的载体,是故事的讲述者。 你是否曾想过,那些令人动容的电影配乐、让人热血沸腾的电音节拍或是清晨唤醒你的温柔闹钟,是如何从一堆杂乱无章的声…

坐牢第二十三天 20240806(IO)

一.作业 1> 使用消息队列完成两个进程之间相互通信 A.c #include <myhead.h> // 要发送的消息类型 struct msgbuf {long mtype; /* message type, must be > 0 */char mtext[1024]; /* message data */ }; #define SIZE sizeof(struct msgbuf) - sizeof(l…

PEPM系统Cookie请求头远程代码执行漏洞复现 [附POC]

文章目录 PEPM系统Cookie请求头远程代码执行漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现PEPM系统Cookie请求头远程代码执行漏洞复现 [附POC] 0x01 前言 免责声明:请勿利用文章内的相关技术从事非法测试,…

mem0ai+ollama+qwen2搭建中文版运行环境

准备模型 支持function的qwen2模型 随便找了一个&#xff0c;也可以下载其他支持function的模型&#xff0c;或者自己下载模型文件搭建 ollama run sam4096/qwen2toolsembedder 模型 ollama run nomic-embed-text拉取mem0ai 源码&#xff0c;切换对应分支 git clone https…

【Foundation】(三)transformers之Model

文章目录 1、介绍1.1、 模型类型1.2、Model Head 2、模型加载3、模型调用3.1、不带Model Head的模型调用3.2、带Model Head的模型调用 4、模型微调实战4.1、导包4.2、加载数据4.3、创建数据集4.4、划分数据集4.5、创建加载器4.6、创建模型以及优化器4.7、模型训练4.8、模型评估…

Figma 替代品 Excalidraw 安装和使用教程

如今远程办公盛行&#xff0c;一个好用的在线白板工具对于团队协作至关重要。然而&#xff0c;市面上的大多数白板应用要么功能单一&#xff0c;要么操作复杂&#xff0c;难以满足用户的多样化需求。尤其是在进行头脑风暴、流程设计或产品原型绘制时&#xff0c;我们常常会遇到…

linux入门到精通-第二十章-bufferevent(开源高性能事件通知库)

目录 参考bufferevent简单介绍工作流程事件Api新建事件节点 bufferevent_socket_new设置事件节点回调bufferevent_setcb使事件势能bufferevent_enable发送数据bufferevent_write接收数据bufferevent_read evconnlistener的简介 参考 视频教程 libevent的基本使用 libevent–bu…

HslCommunicationDemo各品牌Plc通信测试软件工具

目录 1、HslCommunicationDemo程序包 2、ModbusTCP举例说明 (0)概述 &#xff08;1&#xff09;线圈写操作 &#xff08;2&#xff09;寄存器写操作 3、C#工程中DLL库文件使用 &#xff08;1&#xff09;创建Winform程序工程 &#xff08;2&#xff09;写寄存器 1、HslC…

【Linux】匿名管道|命名管道|pipe|mkfifo|管道原理|通信分类|管道的特征和情况

目录 ​编辑 进程间通信 为什么要有进程间通信 进程通信的目的 进程间通信分类 如何理解通信 管道 匿名管道 管道原理 半双工 通信两问 pipe 演示 管道情况 管道的特征 命名管道 mkfifo指令 mkfifo接口 命名管道提供的是流式服务 匿名管道与命名管道的…

day08 1.进程间通信

work1.c #include <myhead.h> //要发送的消息类型 struct msgbuf {long mtype;char mtext[1024]; };#define SIZE sizeof(struct msgbuf)-sizeof(long)int main(int argc, const char *argv[]) {pid_t pid fork();if(pid -1){perror("fork error");return -…

Webpack入门基础知识及案例

webpack相信大家都已经不陌生了&#xff0c;应用程序的静态模块打包工具。前面我们总结了vue&#xff0c;react入门基础知识&#xff0c;也分别做了vue3的实战小案例&#xff0c;react的实战案例&#xff0c;那么我们如何使用webpack对项目进行模块化打包呢&#xff1f; 话不多…

RPA与智慧政务的关系

自1992年国务院明确提出构建全国行政机关办公决策系统&#xff0c;我国政府信息化建设已走过三十余年历程&#xff0c;并取得了阶段性成果&#xff0c;随着社会需求的变化以及信息技术和数字化工具的不断完善&#xff0c;人们对政府的信息化建设也提出了新的要求&#xff0c;推…

【C#语音文字互转】C#语音转文字(方法一)

Whisper.NET开源项目&#xff1a;https://github.com/sandrohanea/whisper.net/tree/main 一. 环境准备 在VS中安装 Whisper.net&#xff0c;在NuGet包管理器控制台中运行以下命令&#xff1a; Install-Package Whisper.net Install-Package Whisper.net.Runtime其中运行时包…

uniapp 实现自定义缩略滚动条

<template><view class"container-scroll"><!-- 文字导航 --><scroll-view class"scroll-view-text" scroll-x"true" v-if"type 1"><navigator:url"item.url"class"scroll-view-item"…

LE-50821F/FA激光扫描传感器|360°避障雷达之功能与连接使用说明

LE-50821F/FA激光扫描传感器|360避障雷达广泛应用于工业自动化、移动机器人应用场景中的环境感知、高精度定位&#xff08;如建图、扫描、避障、防护等&#xff09; LE-50xxxF系列升级扫描频率最高可达600KHz​​​​。 本文重点介绍LE-50821F/FA激光扫描传感器|360避障雷达之…

【C++】二维数组 数组名

二维数组名用途 1、查看所占内存空间 2、查看二维数组首地址 针对第一种用途&#xff0c;还可以计算数组有多少行、多少列、多少元素 针对第二种用途&#xff0c;数组元素、行数、列数都是连续的&#xff0c;且相差地址是有规律的 下面是一个实例 #include<iostream&g…