C复习-结构struct+bit field+union

参考: 里科《C和指针》


结构的声明

struct {int a;char b;
} x;
struct {int a;char b;
} y[20], *z;// 会报错,因为z和x虽然都没有名字,但是并不是一个东西
z = &x;struct SIMPLE {int a;char b;
};
// 这样就对了,因为名字匹配
struct SIMPLE x;
struct SIMPLE* z = &x;// 这样写也ok. 此时SIMPLE是类型名,而非结构体标签,因此可以直接用
typedef struct {int a;char b;
} SIMPLE;
SIMPLE x;
SIMPLE* z = &x;

结构体不能自引用(不能包含同结构成员),但可以包含指向同结构的指针。

struct SELF_REF1 {int a;struct SELF_REF1 b;
}; // 这个会报错,因为SELF_REF1的定义永远在递归,永远没有完成struct SELF_REF2 {int a;struct SELF_REF2 *b; 
}; // 这个是正确的,因为b的长度确定typedef struct {int a;SELF_REF3 *b;
} SELF_REF3; // 这个会报错,因为定义b时还没有SELF_REF3typedef struct SELF_REF3_TAG {int a;struct SELF_REF3_TAG *b;
} SELF_REF3; // 这样是正确的

如果两个结构需要互相依赖(比如一个结构需要包含另一个结构的几个成员),那么至少要有一个结构必须在另一个结构中以指针的形式存在。此时使用不完整声明incomplete declaration。

// 先不完整声明B
struct B;struct A {struct B *partner;...
};struct B {struct A *partner;...
};

结构的初始化

类似数组,用嵌套的大括号。如果初始列表的值不够,剩余的会采用缺省值。

struct INIT_EX {int a;short b[10];Simple c;
} x = {10,{1, 2, 3},{4, 'x'}
};

结构成员的访问

结构成员的直接访问用 . ,间接访问(通过指向结构的指针访问成员)使用 → 。

→的优先级高于&和*

typedef struct {int a;short b[2];
} Ex2;
typedef struct EX {int a;char b[3];Ex2 c;struct Ex *d;
} Ex;
// 此时指针d是NULL
Ex x = { 10, "Hi", { 5, {-1, 25} }, 0 };
Ex *px = &x;// ->优先级高于&所以不用括号
int *pi = &px->a;
int val = px->c.a;
int val2 = *px->c.b; // -1
// *px->d 会报错,所以对指针进行解引用之前一定要检查是否有效

结构存储空间的分配

编译器按照成员列表的顺序分配空间,如果存储时需要满足边界对齐要求,那么成员之间可能出现空白。比如一个机器int占4字节,起始存储位置必须被4整除,系统禁止编译器在struct的起始位置跳过字节来满足对齐要求,那么,对一个结构:

struct ALIGN {char a;int b;char c;
};

其存储结构如下,第一块的第一个字节存a,随后空3个字节,再开始存b,然后进入第三块,第一个字节存c,随后空3个字节。这样可以满足对齐要求,但需要12个字节,空6个。

□■■■|□□□□|□■■■

此时如果重新排列,使得int b在第一行,那么前4个字节可以存b,然后再来4个字节存a和c,最后跳过2个,此时只需要8个字节,空2个。

如果结构数目较少,为了可读性可以将相关的放在一起,但如果有成百上千个结构,为了减少内存浪费,应该考虑重排成员。

使用sizeof可以看整体占的字节数,offsetof则能看到struct某个元素在第几个字节。

#include <stddef.h>
typedef struct {int b;char a;char c;
} ALIGN;int main()
{printf("%d\n", sizeof(ALIGN)); // 8printf("%d\n", offsetof(ALIGN, c)); // 5 return 0;
}

作为函数参数

直接传struct效率很低,因为需要制造拷贝,复制到堆栈中再丢弃。因此一般是传递指针。(除非结构特别特别小,即长度和指针相同或更小)

为了进一步提升效率,可以把参数声明为寄存器变量(如果函数对这个指针的间接访问超过3次,会更省时);同时为了避免修改指针,可以声明为const

// Transaction是一个结构体,这个函数用来打印其中的成员。使用->访问成员
// 如果函数里需要修改某个成员,就去掉const
void print(register Transaction const *trans);

位段bit field

类似struct,但是成员占一个或多个位,最终存储在一个或多个整型变量中。位段的成员只能是int、signed int或unsigned int(最好只用signed和unsigned,因为int被解释为有符号还是无符号是编译器决定的),并且要指明位数。

如果要保证可移植性,那么不要用位段。

优点是可以将长度为奇数的数据包装在一起,节省存储空间;可以很方便地访问一个整型值的部分内容,比如在os中与磁盘控制器通信,方便进行位操作。

struct CHAR {unsigned ch : 7;unsigned font : 6;unsigned size : 19;
};
struct CHAR ch1;

联合Union

union的成员引用的是内存中的相同位置,所以适合不同时刻在同一位置存储不同东西的情况。如果成员们长度不同,union的长度就是最长的成员的长度。

初始化时,初始值必须是第一个成员的类型,如果不符合,会被转换。

union {float f;int i;
} fi = { 1.0f };

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

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

相关文章

生产过程建模在MES管理系统中的重要性

在现代制造业中&#xff0c;为了提升生产效能和满足市场需求&#xff0c;企业纷纷引入MES管理系统解决方案。然而&#xff0c;要成功实施MES管理系统&#xff0c;首要任务是深入理解和有效管理生产过程。为此&#xff0c;建立一个准确且可靠的生产过程模型变得至关重要。 生产…

Web服务器实战

网站需求 1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个网站目录分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于www.openlab.com/student 网站访问学生信息&#xff0c;www.openlab.com/data网站访问教学资料 www…

【2021研电赛】基于深度学习的蛋白质与化合物结合性质预测

本作品介绍参与极术社区的有奖征集|分享研电赛作品扩大影响力&#xff0c;更有重磅电子产品免费领取! 获奖情况&#xff1a;三等奖 1.作品简介 针对药物发现过程中的药物筛选问题&#xff0c;本设计基于深度学习提出新的神经网络结构和数据处理方式用于预测蛋白质与化合物之…

更改 npm的默认缓存地址

npm的默认缓存一般在C:\Users\用户名\AppData\Roaming路径下的npm和npm_cache&#xff0c;而c盘往往空间不大。 1、在其他盘新建两个文件夹&#xff0c;如D盘&#xff0c;node_cache和node_global。如下图所示。 2、在cmd中执行npm config set prefix “node_cache的路径”&a…

关于AM5-DB低压备自投装置如何应用在某变电站项目的-安科瑞 蒋静

摘 要&#xff1a;随着电力需求的不断增加&#xff0c;电力系统供电可靠性要求越来越高&#xff0c;许多供电系统已具备两回或多回供电线路。备用电源自动投入装置可以有效提高供电的可靠性&#xff0c;该类装置能够在工作电源因故障断开后&#xff0c;自动且迅速地将备用电源投…

CF825G Tree Queries

CF825G Tree Queries 洛谷CF825G Tree Queries 题目大意 一棵树有 n n n个节点&#xff0c;初始时均为白色&#xff0c;有两种操作&#xff1a; 1 x表示把结点 x x x染成黑色1 x表示查询 x x x到树上任意一个黑色结点的简单路径上的编号最小的结点的编号 本题强制在线。输…

什么是进销存系统?有哪些流程?

这篇给大家详细介绍一下&#xff0c;到底什么是进销存系统&#xff0c;它的发展历程如何&#xff1f;企业该如何利用进销存系统获得竞争优势&#xff1f; 至于为什么越来越多的企业都选择进销存系统&#xff0c;让我们先来看一下这个实例。 假设有一家零售超市&#xff0c;他…

目标跟踪(DeepSORT)

本文首先将介绍在目标跟踪任务中常用的匈牙利算法&#xff08;Hungarian Algorithm&#xff09;和卡尔曼滤波&#xff08;Kalman Filter&#xff09;&#xff0c;然后介绍经典算法DeepSORT的工作流程以及对相关源码进行解析。 目前主流的目标跟踪算法都是基于Tracking-by-Detec…

PBJ | IF=13.8 利用ChIP-seq和ATAC-seq技术揭示MdRAD5B调控苹果耐旱性的双重分子作用机制

2023年10月24日&#xff0c;西北农林科技大学园艺学院管清美教授团队在Plant Biotechnology Journal&#xff08;最新IF&#xff1a;13.8&#xff09;上发表题为“The chromatin remodeller MdRAD5B enhances drought tolerance by coupling MdLHP1-mediated H3K27me3 in apple…

计算机网络期末复习-Part1

1、列举几种接入网技术&#xff1a;ADSL&#xff0c;HFC&#xff0c;FTTH&#xff0c;LAN&#xff0c;WLAN ADSL&#xff08;Asymmetric Digital Subscriber Line&#xff09;&#xff1a;非对称数字用户线路。ADSL 是一种用于通过电话线连接到互联网的技术&#xff0c;它提供…

Spring定时器是否影响性能

Spring定时器是否影响性能 在Spring中&#xff0c;定时器可以使用不同的技术实现&#xff0c;例如Java自带的Timer类、Spring自带的TaskScheduler、Quartz等。无论使用哪种技术实现&#xff0c;定时器的确会对系统性能产生一定的影响。具体来说&#xff0c;定时器会创建一个或…

安卓系统手机便签app使用哪一款?

在现代快节奏的生活中&#xff0c;我们经常会遇到各种繁忙的事务和容易遗忘的备忘事项。为避免大家遗忘重要的事情&#xff0c;大家可以在常用的手机上安装记录备忘事项的工具&#xff0c;为了帮助安卓用户高效地记录和管理这些信息&#xff0c;今天我将向大家推荐一款功能强大…

关于炒股融资的条件,3个你不知道的小知识

随着投资者对股市的关注度不断提高&#xff0c;炒股融资成为了常见的投资方式&#xff0c;但是很多投资者对炒股融资的条件了解不够。下面给大家介绍三个你可能不知道的小知识。 融资比例的计算方式 融资比例指的是投资者可以借的资金比例&#xff0c;其计算方式是融资金额除以…

阿里云oss迁移到AWS S3

这里写自定义目录标题 0.项目背景1.rclone 方式2.rsync方式3.注意 0.项目背景 公司迁移要求&#xff1a;从阿里云oss到亚马逊s3&#xff0c;数据量大概500G-2T左右。 开启阿里云oss 加速模式&#xff0c;这样能够跨机房和区域加速。 主要采用以下两种方式同步数据&#xff0c;…

uniapp小程序接入腾讯云【增强版人脸核身接入】

文档地址&#xff1a;https://cloud.tencent.com/document/product/1007/56812 企业申请注册这边就不介绍了&#xff0c;根据官方文档去申请注册。 申请成功后&#xff0c;下载【微信小程序sdk】 一、解压sdk&#xff0c;创建wxcomponents文件夹 sdk解压后发现是原生小程序代…

程序员副业之路,今天花几分钟提现了18.1元,感觉认真做收益还是不错的

干客户端这么多年了&#xff0c;越来越觉得力不从心了&#xff0c;以前加班到半夜&#xff0c;睡一觉第二天又生龙活虎继续干&#xff0c;现在时常感叹&#xff1a;年轻就是好呀&#xff0c;有使不完的劲&#xff0c;就像下面这位兄弟这样&#xff0c;跪着都能给你把代码写完。…

对一个以“#”结束的字符串

本题要求编写程序&#xff0c;对一个以“#”结束的字符串&#xff0c;将其小写字母全部转换成大写字母&#xff0c;把大写字母全部转换成小写字母&#xff0c;其他字符不变输出。 输入格式&#xff1a; 输入为一个以“#”结束的字符串&#xff08;不超过30个字符&#xff09;…

Halcon如何使用SaperaLT库连接dalsa相机

halcon安装好的时候&#xff0c;没有带SaperaLT的采集库&#xff0c;需要额外在Halcon官网下载此库。 以下是halcon官网下载此库的链接。官网需要注册才可以下载。 https://www.mvtec.com/downloads/interfaces?tx_mvtecproduct_extensiondownloadlist%5Bfilter%5D%5B0%5Dma…

CC1101 一款低功耗sub- 1ghz收发器芯片 适用于无线遥控智能家居

产品描述 CC1101是一个低成本的sub- 1ghz收发器,专为极低功耗的无线应用而设计。 该电路主要用于工业、科学和医学)和SRD (Short Range Device)频带,在315,433,868和915兆赫&#xff0c;但可以轻松可编程用于其他操作频率在300-348 MHz、387-464 MHz,以及779-928 MHz频段。射…

linux服务器超简单安装配置nginx

1.更新软件源索引并安装 Nginx 对于 CentOS/RHEL: sudo yum update sudo yum install nginx 对于 Ubuntu/Debian: sudo apt update sudo apt install nginx 2.启动 Nginx sudo systemctl start nginx 3.设置 Nginx 开机自启动 sudo systemctl enable nginx 此时 N…