C语言-结构体尺寸

CPU字长

字长的概念指的是处理器在一条指令中的数据处理能力,当然这个能力还需要搭配操作系统的设定,比如常见的32位系统、64位系统,指的是在此系统环境下,处理器一次存储处理的数据可以达32位或64位。

地址对齐

当计算机系统的CPU字长确定后,就意味着每次CPU从内存中读取或写入数据时都会以固定的边界进行操作。以32位系统为例,这意味着CPU每次操作都会以4字节(32位)为单位。

如果所需数据恰好在这个4字节的边界上,我们称其为地址对齐的。这样的数据读取或写入会更高效,因为CPU可以直接按照这个边界进行操作。

而如果数据跨越了这个边界,使用了超过所需单元的字节,我们称其为地址未对齐的。这会导致额外的处理工作,可能会降低效率,并且在某些系统上可能会导致错误或异常。

地址对齐是一种优化技术,有助于提高系统的性能和稳定性。

 地址未对齐的情形                                                                地址已对齐的情形

从图中可以明显看出,数据本身占据了8个字节,在地址未对齐的情况下,CPU需要分3次才能完整地存取完这个数据,但是在地址对齐的情况下,CPU可以分2次就能完整地存取这个数据。

总结:
如果一个数据满足以最小单元数存放在内存中,则称它地址是对齐的,否则是未对齐的。地址对齐的含义用大白话说就是1个单元能塞得下的就不用2个;2个单元能塞得下的就不用3个。
如果发生数据地址未对齐的情况,有些系统会直接罢工,有些系统则降低性能。

普通变量的m值

以32位系统为例,由于CPU存取数据总是以4字节为单元,因此对于一个尺寸固定的数据而言,当它的地址满足某个数的整数倍时,就可以保证地址对齐。这个数就被称为变量的m值。
根据具体系统的字长,和数据本身的尺寸,m值是可以很简单计算出来的。

  • 举例 ( 注意,变量的m值跟变量本身的尺寸有关,但它们是两个不同的概念)
char   c; // 由于c占1个字节,因此c不管放哪里地址都是对齐的,因此m=1
short  s; // 由于s占2个字节,因此s地址只要是偶数就是对齐的,因此m=2
int    i; // 由于i占4个字节,因此只要i地址满足4的倍数就是对齐的,因此m=4
double f; // 由于f占8个字节,因此只要f地址满足4的倍数就是对齐的,因此m=4

printf("%p\n", &c); // &c = 1*N,即:c的地址一定满足1的整数倍
printf("%p\n", &s); // &s = 2*N,即:s的地址一定满足2的整数倍
printf("%p\n", &i); // &i = 4*N,即:i的地址一定满足4的整数倍
printf("%p\n", &f); // &f = 4*N,即:f的地址一定满足4的整数倍
  • 手工干预变量的m值:
char c __attribute__((aligned(32))); // 将变量 c 的m值设置为32
  • 语法:
    • attribute 机制是GNU特定语法,属于C语言标准语法的扩展。
    • attribute 前后都是双下划线,aligned两边是双圆括号。
    • attribute 语句,出现在变量定义语句中的分号前面,变量标识符后面。
    • attribute 机制支持多种属性设置,其中 aligned 用来设置变量的 m 值属性。
    • 一个变量的 m 值只能提升,不能降低,且只能为正的2的n次幂。

结构体的M值

  • 概念:
    • 结构体的M值,取决于其成员的m值的最大值。即:M = max{m1, m2, m3, …};
    • 结构体的和地址和尺寸,都必须等于M值的整数倍。
  • 示例:
struct node
{
    short  a; // 尺寸=2,m值=2
    double b; // 尺寸=8,m值=4
    char   c; // 尺寸=1,m值=1
};

struct node n; // M值 = max{2, 4, 1} = 4;
  • 以上结构体成员存储分析:
    • 结构体的M值是4,这意味着结构体的地址和尺寸都必须是4的倍数。
    • 成员a的M值是2,但由于它是结构体的首元素,必须满足结构体的M值约束,所以a的地址必须是4的倍数。
    • 成员b的M值是4,所以在a和b之间需要填充2个字节的无效数据(通常是0),以保证b的地址是4的倍数。
    • 成员c的M值是1,它直接紧挨在b的后面,占据一个字节的空间。
    • 为了让结构体的尺寸满足4的倍数,c后面还需要填充3个字节的无效数据。
  • 以上结构体成员图解分析:

结构体成员布局

可移植性

可移植指的是相同的一段数据或者代码,在不同的平台中都可以成功运行。

  • 对于数据来说,有两方面可能会导致不可移植:
    • 数据尺寸发生变化
    • 数据位置发生变化
  • 第一个问题,是基本的数据类型在不同的系统所占据的字节数不同造成的,解决办法如下

使用可移植性数据类型来解决基本数据类型在不同系统中占据的字节数不同的问题。可移植性数据类型是指具有固定大小的数据类型,无论在何种平台上都具有相同的大小。在C语言中,可以使用<stdint.h>头文件中定义的标准整数类型来实现可移植性。这些类型包括int8_tint16_tint32_tint64_t等,它们分别表示有符号整数类型,且确保在任何平台上都有固定的字节数。 

示例:

#include <stdint.h>

int8_t   // 有符号8位整数
int16_t  // 有符号16位整数
int32_t  // 有符号32位整数
int64_t  // 有符号64位整数
  • 第二个问题,即数据位置的可移植性,可以通过使用特定的编译指令或者技术来解决

        解决这个问题的两种方法如下:

  1. 第一种方法是通过使用编译器提供的特性,固定每个成员的对齐方式,从而固定成员之间的间隔,确保结构体在不同平台上的布局一致。在这个例子中,通过使用`__attribute__((aligned(n)))`,指定每个成员的对齐方式,其中`n`为对齐值。这样,每个成员之间的间隔就是固定的。
    struct node
    {
        int8_t  a __attribute__((aligned(1))); // 将 m 值固定为1
        int64_t b __attribute__((aligned(8))); // 将 m 值固定为8
        int16_t c __attribute__((aligned(2))); // 将 m 值固定为2
    };
    
  2. 第二种方法是使用`__attribute__((packed))`属性,这会告诉编译器不要在结构体成员之间插入任何填充字节,从而让结构体的布局更加紧凑。这种方法会减少内存的浪费,但可能会降低访问效率,因为访问未对齐的数据可能会导致性能损失。

        

struct node
{
    int8_t  a;
    int64_t b;
    int16_t c;
} __attribute__((packed));

无论使用哪种方法,都可以确保结构体在不同平台上的布局一致,从而提高了数据的可移植性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day 32 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

买卖股票的最佳时期Ⅱ 给定一个数组&#xff0c;它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;。 注意&#xff1a;你不能同时参与多笔交易&#xff08;你…

RAKsmart洛杉矶大带宽服务器支持哪些操作系统?

RAKsmart洛杉矶大带宽服务器支持多种操作系统。具体包括以下几种&#xff0c;rak部落小编为您整理发布RAKsmart洛杉矶大带宽服务器支持哪些操作系统? RAKsmart作为一家提供海外服务器租用服务的公司&#xff0c;其洛杉矶大带宽服务器支持安装和运行多种操作系统。 这些操作系统…

WebServer项目介绍文章【四叶专属】

Linux项目实战C轻量级Web服务器源码分析TinyWebServer 书接上文&#xff0c;学习开源项目的笔记没想到居然有不少阅读量&#xff0c;后面结合另一个前端开源项目简单做了点修改&#xff0c;没想到居然有需要的同学&#xff0c;那么我就专门为四叶开一篇文章吧&#xff0c;【源码…

探索区块链世界:赋能创新,揭示区块链媒体发稿的影响力-世媒讯

区块链&#xff0c;这个由“区块”和“链”组成的概念&#xff0c;可能在您眼中充满神秘和复杂&#xff0c;但其实甚至无所不在&#xff0c;它正静悄悄地改变着我们日常生活的方方面面&#xff0c;从金融到媒体&#xff0c;从医疗到教育。 我们来揭开区块链的神秘面纱。区块链…

前端零代码开发实践:页面嵌套+逻辑连线0开发扩展组件,实现切换开关控制扇叶转动。能无代码封装扩展组件,有别于常规的web组态或低代码平台

前言&#xff1a; 官网:http://www.uiotos.net/ 什么是 UIOTOS&#xff1f; 这是一款拥有独创专利技术的前端零代码工具&#xff0c;专注于解决前端界面开发定制难题&#xff0c;原型即应用&#xff01;具有页面嵌套、属性继承、节点连线等全新特性&#xff0c;学习门槛低…

AI 智能工具以及热门AI开源项目整理,包含国内中科院版GPT

AI 智能工具以及热门AI开源项目整理&#xff0c;包含国内中科院版GPT。 不用xx即可访问的镜像网站 https://chat1.yqcloud.top https://chat.bnu120.space https://chat.aidutu.cn https://hzdjs.cn/chatgpt https://chats.fenqubiao.com/zh 需要xx才能访问的网站 https://o…

金融时报:波场亮相哈佛大学并举办TRON Builder Tour活动

近日,波场TRON作为顶级白金赞助商出席哈佛区块链会议并成功举办TRON Builder Tour哈佛站活动,引发海外媒体热议。美联社、金融时报、Cointelegraph等国际主流媒体及加密知名媒体均对此给予了高度评价,认为本次大会对TRON Builder Tour活动具有里程碑意义,彰显了波场TRON致力于促…

spring security登录认证授权

spring security登录认证授权 是什么 Spring Security 主要实现了Authentication&#xff08;认证&#xff0c;解决who are you? &#xff09; 和 Access Control&#xff08;访问控制&#xff0c;也就是what are you allowed to do&#xff1f;&#xff0c;也称为Authorizat…

HTTP与SOCKS-哪种协议更适合您的代理需求?

网络代理技术是我们日常使用网络时必不可少的一项技术&#xff0c;它可以为我们提供隐私保护和负载均衡的能力&#xff0c;从而保证我们的网络通信更加安全和顺畅。而其中最主流的两种协议就是HTTP和SOCKS。虽然它们都是用于网络代理的协议&#xff0c;但在实际应用中却存在着一…

Java | Leetcode Java题解之第45题跳跃游戏II

题目&#xff1a; 题解&#xff1a; class Solution {public int jump(int[] nums) {int length nums.length;int end 0;int maxPosition 0; int steps 0;for (int i 0; i < length - 1; i) {maxPosition Math.max(maxPosition, i nums[i]); if (i end) {end maxP…

【网络安全】XSS漏洞注入,分类,防御方法

1.什么是XSS XSS全称&#xff08;Cross Site Scripting&#xff09;跨站脚本攻击&#xff0c;是最常见的Web应用程序安全漏洞之一&#xff0c;仅次于SQL注入。XSS是指攻击者在网页中嵌入客户端脚本&#xff0c;通常是JavaScript编写的危险代码&#xff0c;当用户使用浏览器浏览…

Linux——NFS网络文件系统

在生产环境中共享宿主目录可以用于集中管理账户 一、存储设备 DAS 是直连存储相当于移动硬盘 NAS 是网络文件系统&#xff0c;挂载后可以直接访问 SAN 存储区域网络 IPSAN 网线连接 共享的是设备&#xff0c;需要挂载后分区使用 FCSAN 光纤连接 二、服务的管理 1、安…

数据结构练习-线性表定义与基本操作

----------------------------------------------------------------------------------------------------------------------------- 1. 线性表是( )。 A.一个有限序列&#xff0c;可以为空 B. 一个有限序列&#xff0c;不可以为空 C. 一个无限序列&#xff0c;可以为空…

编译报错 - Missing trailing comma comma-dangle or Missing semicolon semi

一、comma-dangle规则&#xff1a; 这种错误通常出现在使用代码格式检查工具&#xff08;如ESLint&#xff09;时&#xff0c;具体是在JSON或者JavaScript对象、数组的最后一个元素后面缺少了逗号&#xff08;trailing comma&#xff09;。在某些编码标准中&#xff0c;要求在…

SS34B-ASEMI超低Low VF肖特基SS34B

编辑&#xff1a;ll SS34B-ASEMI超低Low VF肖特基SS34B 型号&#xff1a;SS34B 品牌&#xff1a;ASEMI 封装&#xff1a;SMB 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;3A 最大循环峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;40V 最大正向电压…

idea同步yapi插件

1、前言 yapi是一个很好的接口文档维护工具&#xff0c;其swagger功能&#xff0c;可将接口信息同步到yapi平台上&#xff0c;但是swagger的编写&#xff0c;大量入侵代码&#xff0c;也加大了开发工作量&#xff0c;目前调研了idea集成yapi同步工具&#xff0c;无需嵌入式编写…

echart图标区域背景

效果图&#xff1a; 代码实例&#xff1a; let option {calculable: true,legend: {orient: vertical,top: 10%,left: right},tooltip: {show: true,formatter: {a} {b} : {c} },xAxis: [{type: category,data: Array.from({ length: 12 }).map((a, index) > ${index 1}月…

MySQL、Oracle查看最大连接数和当前连接数

文章目录 1. MySQL2. Oracle 1. MySQL -- 查看最大连接数 show variables like max_connections; select max_connections; -- select * from performance_schema.session_variables where VARIABLE_NAME in (max_connections); -- select * from performance_schema.global…

DFS与回溯专题:二叉树的最大深度

DFS与回溯专题&#xff1a;二叉树的最大深度 题目链接: 104.二叉树的最大深度 题目描述 代码思路 设置两个变量&#xff0c;max来记录最大值&#xff0c;sum来记录路径的节点数量。利用dfs对二叉树进行搜索&#xff0c;遇到节点&#xff0c;则sum1&#xff1b;遇到叶子节点&…

【网络编程】网络编程中的基本概念及Java实现UDP、TCP客户端服务器程序(万字博文)

系列文章目录 【网络通信基础】网络中的常见基本概念 【网络编程】网络编程中的基本概念及Java实现UDP、TCP客户端服务器程序&#xff08;万字博文&#xff09; 【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制&#xff08;CRC算法、MD5算法&#xff09; 文章目…