跟我学C++中级篇——零长度数组

一、零长度数组

最初使用零长度数组是在串口通信和网络通信中使用的,它类似于下面的代码:

struct Data
{int a;char c;char buf[0];
};

零长度数组又叫柔性数组,这个非常贴切。它早期是GNU的一个扩展,后来在C99中也进行了支持(-pedantic 禁用扩展),不过在C99中使用时,就不用写那个0了。如果在早期的VC或者其它平台上不支持这种零长度数组的,可以考虑使用一些变通的方式。

二、应用场景

零长度数组主要用来对一些不确定长度的通信负载的内容进行接收。在C/C++的编码过程中,有一个小的技巧,即可以把char*指针强转到结构体的指针,这样就可以直接操作结构体。这对于网络或者串口等通信中有着很强的优势(需要处理一下字节对齐)。

那么有人会问为什么不使用指针呢?或者给一个很长的固定数组。首先,给定一个很长的数组,到底多长是很长?如果能确定最多不过一百个,那么用一百个长度来取代零长度数组可能会更好,但可能跨度很大呢,从几个字节长度到几兆字节长度呢?有人可能说,谁会设计这种协议呢?可有的时候儿协议不是自己设计的,用别人的怎么办?那么这时候儿用零长度指针就非常好用。
那为什么不用指针呢?学习过编译相关知识的都知道,指针指向的地址空间,一般情况下是不会和指针当前的地址连续的,以上面的Data结构体为例,如果创建一个对象,使用零长度数组,所有的字节其实是从变量a依次按顺序向下排列的,是线性的。但如果把buf定义成一个指针,那么buf本身这个地址是排在最后的,但对应的指针指向的空间,则指向了另外一个空间地址。表面上创建了一个Data对象,但其是有两块地址空间被分配,这两块地址空间并不连续。不连续意味着什么?意味着上面提到的将char*强转成指定的结构体指针成为了不可能。因为buf得到的地址空间,未必是原来定义的空间,这个在硬件通信中非常明显。
最好的方法就是,直接传输一大段数据,这些数据是连续的存储在一起的,那么通过强转就可直接进行数据操作,可数据长度又是未知的,而普通的数组长度必须是提前指定的,这就是一个矛盾,所以零长度数组的优势就体现出来了。它其实相当于一个占位符,告诉空间分配者,这后面还有一大堆的数据,至于多长,根据实际情况来定。零长度数组等于是取了个巧,既符合了标准中的数组长度必须提前固定,又实现了指针的变长分配。

三、例程

下面看一个模拟的例程:

struct DataWater {int count;float size;char buf[0];
};
char dbuf[1024] = {0};
void testZeroArray(char *data) {DataWater *dw;dw = (DataWater *)data;std::cout << dw->count << std::endl;
}
int main() {testZeroArray(dbuf);return 0;
}

假如testZeroArray函数是一个接收串口通信或者网络通信的协议结构体,而data就是通过接收得来的一个字节流,那么这个函数的代码就可以直接解析出来协议的内容并为程序所用。

四、总结

其实零长度数组是一个技巧,这样的小技巧在C/C++中有很多。它们在一些特定的场景下有着非常好的应用,不过前面的定语一定要记清楚,特定的场景。这也是C/C++让初学者感到难缠的一个重要原因。到处都有一些特殊情况,而特殊情况里可能又套着特殊情况。
这种小技巧的东西,不用刻意学习,用到了,想起来有,查查资料用就可以了。

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

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

相关文章

【经典面试题】JavaScript中的异步操作与回调地狱解决方法

JavaScript中的异步操作与回调地狱解决方法 在现代的Web开发中&#xff0c;JavaScript扮演着极为重要的角色&#xff0c;尤其是在处理网络请求、文件操作或者任何可能耗费时间的操作时。为了不阻塞程序的执行&#xff0c;JavaScript 提供了异步编程模型。本文将介绍JavaScript…

vue3 使用pinia -- vue2 vuex的plus版

接入状态store 即 vuex 呃(⊙﹏⊙)vuex这里可以略过了&#xff0c;我在研究完后&#xff0c;才发现vue3出来个pinia&#xff0c;是vuex的升级&#xff0c;体积更小更省事&#xff0c;我不删这里了&#xff0c;单纯记录下&#x1f642; --pinia用法下面有写哦 ① 执行 npm insta…

C# 实现格式化文本导入到Excel

目录 需求 Excel 的文本文件导入功能 范例运行环境 配置Office DCOM 实现 组件库引入 OpenTextToExcelFile 代码 调用 小结 需求 在一些导入功能里&#xff0c;甲方经常会给我们一些格式化的文本&#xff0c;类似 CSV 那样的纯文本。比如有关质量监督的标准文件&…

LangChain 入门6 magic不同格式文件的读取

概述&#xff1a; 除了原始文本数据&#xff0c;可能还希望从其他文件类型&#xff08;如PowerPoint演示文稿或PDF&#xff09;中提取信息。 可以使用LangChain文档加载程序将文件解析为可以输入LLM的文本格式。 基于MIME类型的解析 数据加载 import requestsresponse req…

如何理解和实现二分查找:一篇完整的解析

二分查找的基本思想 二分查找的核心思想是比较数组的中间元素与目标值。根据比较结果&#xff0c;可以排除一半的搜索空间。具体步骤如下&#xff1a; 初始化指针&#xff1a;设置两个指针&#xff0c;left 指向数组的开始位置&#xff0c;right 指向数组的结束位置。 循环搜索…

手写线程池|C语言版(二)|定义线程池的结构、创建线程池实例

文章目录 定义线程池结构任务结构体定义线程池结构体 组织头文件创建线程池实例函数原型定义线程池创建函数实现初始化线程池结构体指针初始化线程池结构体的各类参数 定义线程池的结构C代码创建线程池总体C代码 本文中&#xff0c;我们将创建线程池的结构体&#xff0c;该结构…

TCP/IP和HTTP协议

TCP/IP OSI 七层模型在提出时的出发点是基于标准化的考虑&#xff0c;而没有考虑到具体的市场需求&#xff0c;使得该模型结构复杂&#xff0c;部分功能冗余&#xff0c;因而完全实现 OSI 参考模型的系统不多。而 TCP/IP 参考模型直接面向市场需求&#xff0c;实现起来也比较…

一文掌握:Clipboard API ,让前端顺畅操作剪贴板,无论怎么复制,都显示你网站信息。

一、Clipboard API是什么 Clipboard API 是一个 Web API&#xff0c;它提供了一种在网页上读取和写入剪贴板内容的方式。通过 Clipboard API&#xff0c;网页可以访问用户的剪贴板&#xff0c;从中读取文本、图像或其他数据&#xff0c;并且可以将数据写入剪贴板&#xff0c;以…

FFmpeg基础知识详解:音频视频处理的强大工具

FFmpeg&#xff0c;这个强大的开源多媒体框架&#xff0c;已经成为全球范围内音频、视频处理和流媒体传输领域的基石。它集合了音频解码、编码、转码、混合、抓取、流化等多种功能于一身&#xff0c;几乎能满足任何与音视频处理相关的技术需求。本文将带你走进FFmpeg&#xff0…

2024五一杯C题思路代码文章成品分享:煤矿深部开采冲击地压危险预测

提供的数据分为五类&#xff1a; A:正常工作数据 B:前兆特征数据 C:干扰信号数据 D:传感器断线数据 E:工作面休息数据 任务细节&#xff1a; 任务1&#xff1a; 分析含干扰的电磁辐射和声发射信号&#xff0c;识别干扰信号的特征&#xff0c;并利用这些特征在特定时间段…

安装Kuboard管理k8s

一、Kuboard 介绍 Kuboard 是一款免费的 Kubernetes 管理工具,提供了丰富的功能,结合已有或新建的代码仓库、镜像仓库、CI/CD工具等,可以便捷的搭建一个生产可用的 Kubernetes 容器云平台,轻松管理和运行云原生应用。您也可以直接将 Kuboard 安装到现有的 Kubernetes 集群…

计算机毕业设计python_django宠物领养系统z6rfy

本宠物领养系统主要包括两大功能模块&#xff0c;即管理员模块、用户模块。下面将对这两个大功能进行具体功能需求分析。 &#xff08;1&#xff09;管理员&#xff1a;管理员登录后主要功能包括个人中心、用户管理、送养宠物管理、地区类型管理、失信黑名单管理、申请领养管理…

深入解析Jackson的ObjectMapper:核心功能与方法指南

com.fasterxml.jackson.databind.ObjectMapper 是Jackson库的核心类&#xff0c;负责JSON序列化与反序列化的重任。本文旨在详细介绍其成员属性和方法&#xff0c;帮助开发者更好地利用Jackson进行Java对象与JSON数据之间的转换操作。 初始化与配置 构造与复制 默认构造函数…

封装umi-request时通过 AbortController 配置取消请求

一、关键部分 一、在封装的request.ts中 声明一个 abortControllers 对象用于存储要取消的请求&#xff08;我用了-s表示复数&#xff0c;多个abortcontroller对象&#xff0c;与下面&#x1f447;的单个abortController区分&#xff09;封装取消请求的函数cancelRequest, 传入…

038——基于STM32和I.MX6uLL实现uart控制GPS(失败者总结)

目录 1、GPS模块简介 2、GPS数据格式 3、方案梳理 1、GPS模块简介 全球定位系统(Global Positioning System&#xff0c; GPS)是一种以空中卫星为基础的高精度无线电导航的定位系统&#xff0c;它在全球任何地方以及近地空间都能够提供准确的地理位置、车行速度及精确的时间…

邦注科技 温控箱对企业的重要性

注塑加工是将加热的熔融塑料注入模具中形成所需产品的工艺过程。良好的注塑加工工艺需要控制好许多参数&#xff0c;其中最重要的因素之一就是模具的温度。模具温度的不稳定会导致产品尺寸大小、表面缺陷等方面的问题&#xff0c;甚至会导致生产不良品&#xff0c;加大生产成本…

【webrtc】MessageHandler 5: 基于线程的消息处理:以PeerConnection信令线程为例

peerconn的信令是通过post 消息到自己的信令线程消息来处理的PeerConnectionMessageHandler 是具体的处理器G:\CDN\rtcCli\m98\src\pc\peer_connection_message_handler.hMachinery for handling messages posted to oneself PeerConnectionMessageHandler 明确服务于 signalin…

2021江苏省赛 H-Reverse the String

来源 题目 There is a string of lowercase letters, and you want to minimize its lexicographical order. What you can do is reverse an interval or do nothing. For example, for the string abcdefg, if we reverse the interval abcdefg, it will become abfedcg. A …

017、Python+fastapi,第一个Python项目走向第17步:ubuntu24.04 无界面服务器版下安装nvidia显卡驱动

一、说明 新的ubuntu24.04正式版发布了&#xff0c;前段时间玩了下桌面版&#xff0c;感觉还行&#xff0c;先安装一个服务器无界面版本吧 安装时有一个openssh选择安装&#xff0c;要不然就不能ssh远程&#xff0c;我就是没选&#xff0c;后来重新安装ssh。 另外一个就是安…

数据仓库和数据仓库分层

一、数据仓库概念 数据仓库(Data Warehouse)&#xff0c;可简写为DW或DWH。数据仓库&#xff0c;是为企业所有级别的决策制定过程&#xff0c;提供所有类型数据支持的战略集合。它是单个数据存储&#xff0c;出于分析性报告和决策支持目的而创建。 为需要业务智能的企业&#…