C语言-柔性数组成员的使用

文章目录

    • 摘要
    • 柔性数组成员
      • 基本使用
      • 细节探究
    • 零长度数组-定长数组-变长数组

摘要

本文先介绍柔性数组成员(flexible array member)的基本使用,然后介绍其内存结构。最后,补充了一些数组相关的其他概念。


柔性数组成员

基本使用

参考: 【C语言内功修炼】柔性数组的奥秘_数组_Albert Edison_InfoQ写作社区

C99之后,可以使用 flexible array member。它大概长下面这个样子。

struct buffer {unsigned int len;char contents[]; // flexible array member
};
  • flexible array member 可以认为是零长度数组实现的一个特例(下文会介绍零长度数组)。sizeof(buffer.contents)的值为0。
  • flexible array member 只能作为结构体的最后一个成员

下面我们看一个demo,来体验下 flexible array member 带来的便利。

这个demo比较简单。分配一个缓冲区,往里面写内容。这个缓冲区保有缓冲区的大小。

// demo-1.c
#include <stdio.h>
#include <stdlib.h>struct buffer {unsigned int len;char contents[];
};int main(int argc, char *argv[]) {unsigned int buf_len = 100;// construct a bufferstruct buffer *buffer =malloc(sizeof(struct buffer) + buf_len * (sizeof(char)));buffer->len = buf_len;snprintf(buffer->contents, buffer->len, "%s", "hello world");printf("%s\n", buffer->contents);free(buffer);return 0;
}

如果不使用柔性数组,下面这样,可以实现同样的功能。而且也非常简单。

//demo-2.c
#include <stdio.h>
#include <stdlib.h>struct buffer {unsigned int len;char *contents;
};int main(int argc, char *argv[]) {unsigned int buf_len = 100;// construct a bufferstruct buffer *buffer =malloc(sizeof(struct buffer) + buf_len * (sizeof(char)));buffer->contents = (char *)buffer + sizeof(struct buffer);buffer->len = buf_len;snprintf(buffer->contents, buffer->len, "%s", "hello world");printf("%s\n", buffer->contents);free(buffer);return 0;
}

这两者有什么区别呢?下一节我们来探究下。


细节探究

参考:Zero Length (Using the GNU Compiler Collection (GCC))

首先,上面demo中,struct buffer的大小是不同的。我这里直接给出大小。这个大小可以通过打印或者gdb方式获取。

// 当前环境
Linux da1234cao 5.15.133.1-microsoft-standard-WSL2 x86_64 GNU/Linux// demo-2中buffer结构体
// sizeof(struct buffer) == 16 ; sizeof(char*) == 8
struct buffer {unsigned int len;char *contents;
};// demo-1中buffer结构体
// sizeof(struct buffer) == 4 ; sizeof(buffer.contents) == 0
struct buffer {unsigned int len;char contents[];
};// 修改下flexible array member的类型
// sizeof(struct buffer) == 8 ; sizeof(buffer.contents) == 0
struct buffer {unsigned int len;long contents[];
};

可以看到 flexible array member 的空间大小为0。但由于尾部填充,flexible array member 可能会导致结构体的空间变大,其空间对齐方式,与 flexible array member 的类型相同。我们知道指针是可以进行加法运算的,同样,它的偏移量由 flexible array member 的类型决定。

此时,我们来绘制下包含 flexible array member 结构体的内存结构。

在这里插入图片描述

而上面demo-2.c中的结构体内存则是这样。

在这里插入图片描述

最后,我不建议将一个包含 flexible array member 的结构体,嵌套到其他结构体中,虽然这样做是允许的。如果你想这么做的话,请自行参考官方手册。我没太看懂这块。

Tips: 如果结构体中包含 flexible array member , 可以放心的将结构体进行memset操作。flexible array member 总是指向后面的位置。


零长度数组-定长数组-变长数组

通过上一节,我们已经掌握了 flexible array member 的使用。这里补充些其他相关的基本概念。

零长度数组

可以认为 flexible array member 是零长度数组的一种实现。 flexible array member 是在C99之后出现的。在C99之前,程序员们这样使用零长度数组。

struct line {int length;char contents[0]; // [] 中多了一个0
};

上面的代码和 flexible array member 效果相同。但是,在C99之后,请使用 flexible array member 。按照手册写代码,我不知道有没有什么原因或者好处。

定长数组

在C99之前,数组在创建的时候,必须给定一个常量。这个数组长度在编译的时候,已经确定。

// 定长数组
char array[10];// 下面这个也是定长数组
// 可以参考下 《C语言程序设计 -- 现代方法》8.1.2 数组初始化
// 如果给定了初始化式,可以省略掉数组的长度; 编译器利用初始化式的长度来确定数组的大小。数组仍然有固定数量的元素;
char array[] = {'a', 'b', 'c'};

变长数组

参考: Variable Length (Using the GNU Compiler Collection (GCC))

数组长度在运行时确定。

int n = 10;
char array[n];

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

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

相关文章

[项目设计] 从零实现的高并发内存池(一)

&#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[高并发内存池] ❤️ 前置学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 ​ 目录 前言 项目介绍 1.内存池 1.1 什么是内存池 池化技术 内存池 1.2 为什…

word使用bib添加参考文献

文章目录 安装TexLive安装bibtex4word使用在word中添加参考文献使用bibtex4word在word中添加参考文献设置参考文献格式为毕业论文格式 参考 安装TexLive 从下载地址下载镜像iso文件texlive2023.iso双击打开iso镜像文件运行 install-tl-windows.bat点击安装非常非常非常耐心地安…

Shell学习 - 2.20 Shell exit命令:退出当前进程

exit 是一个 Shell 内置命令&#xff0c;用来退出当前 Shell 进程&#xff0c;并返回一个退出状态&#xff1b;使用$?可以接收这个退出状态&#xff0c;这一点已在《Shell $?》中进行了讲解。 exit 命令可以接受一个整数值作为参数&#xff0c;代表退出状态。如果不指定&…

Linux命令-clock命令(用于调整 RTC 时间)

说明 clock命令用于调整 RTC 时间。 RTC 是电脑内建的硬件时间&#xff0c;执行这项指令可以显示现在时刻&#xff0c;调整硬件时钟的时间&#xff0c;将系统时间设成与硬件时钟之时间一致&#xff0c;或是把系统时间回存到硬件时钟。 语法 clock [--adjust][--debug][--dir…

客户端/服务器协议是啥意思?

客户端/服务器协议是指在网络通信中&#xff0c;客户端和服务器之间进行数据传输时所使用的规定。简单来说&#xff0c;客户端是用户使用的设备&#xff0c;如电脑或手机&#xff0c;而服务器则是提供数据或服务的远程计算机。当客户端需要获取数据或服务时&#xff0c;它会向服…

【RT-DETR有效改进】结合SOTA思想利用双主干网络改进RT-DETR(全网独家创新,重磅更新)

一、本文介绍 本文给大家带来的改进机制是结合目前SOTAYOLOv9的思想利用双主干网络来改进RT-DETR&#xff08;本专栏目前发布以来改进最大的内容&#xff0c;同时本文内容为我个人一手整理全网独家首发 | 就连V9官方不支持的模型宽度和深度修改我都均已提供&#xff0c;本文内…

【活动】金三银四,前端工程师如何把握求职黄金期

随着春意盎然的气息弥漫大地&#xff0c;程序员群体中也迎来了一年一度的“金三银四”求职热潮。这个时间段对于广大前端工程师而言&#xff0c;不仅象征着生机勃发的新起点&#xff0c;更是他们职业生涯中至关重要的转折点。众多知名公司在这一时期大规模开启招聘通道&#xf…

ChatGPT 4.0使用之论文阅读

文章目录 阅读环境准备打开AskYourPDF进入主站 粗读论文直接通过右侧边框进行提问选中文章内容翻译或概括插图的理解 总结 拥有了GPT4.0之后&#xff0c;最重要的就是学会如何充分发挥它的强大功能&#xff0c;不然一个月20美元的费用花费的可太心疼了&#xff08;家境贫寒&…

WP外贸营销型网站模板

WordPress外贸独立站主题 简洁实用的WordPress外贸独立站主题&#xff0c;适合时尚服装行业搭建wordpress企业官网使用。 零件配件WordPress外贸建站模板 汽车行业零配件WordPress外贸建站模板&#xff0c;卖配件、零件的外贸公司可以使用的WordPress主题。 https://www.jia…

RocketMQ—消费者的两种消费模式

RocketMQ—消费者的两种消费模式 RocketMQ消息消费的模式分为两种&#xff1a;负载均衡模式和广播模式&#xff0c;负载均衡模式表示多个消费者交替消费同一个主题里面的消息&#xff1b;广播模式表示每个每个消费者都消费一遍订阅的主题的消息。 负载均衡模式 CLUSTERING 集…

vue2 element 实现表格点击详情,返回时保留查询参数

先直观一点&#xff0c;上图 列表共5条数据&#xff0c;准备输入Author过滤条件进行查询 进入查看详情页&#xff0c;就随便搞了个按钮 啥都没调啦 点击返回后 一开始准备用vuex做这个功能&#xff0c;后来放弃了&#xff0c;想到直接用路由去做可能也不错。有时间再整一套…

一篇文章了解和使用Map和Set(HashMap/TreeMap/HashSet/TreeSet)

[本节目标] *掌握HashMap/TreeMap/HashSet/TreeSet的使用 *掌握了解HashSet和HashSet背后的哈希原理和简单的实现 1. 搜索树 1.1 概念 二叉搜索树又称二叉排序树,它或者是一颗空树,或者是具有以下性质的二叉树: 1.若它的左子树不为空&#xff0c;则左子树上所有节点的值都…

【一起学习Arcade】(2):Geometry函数

第二篇记录下Geometry函数&#xff0c;相对于其它语言&#xff0c;Arcade对Geometry的支持是一大亮点&#xff0c;这使得它的上限被大大提高了。 三、Geometry函数 1、Angle【角度】 单位为度&#xff08;0-360&#xff09;&#xff0c;正北为90度&#xff0c;只考虑x-y平面。…

07OpenCV 图像模糊

文章目录 图像掩膜操作模糊原理均值滤波高斯滤波中值滤波双边滤波算子代码 图像掩膜操作 图像掩膜操作 模糊原理 Smooth/Blur是图像处理中最简单和常用的操作之一 使用操作的原因之一就是为了给图像预处理时候减低噪声 图像噪声是指存在于图像数据中的不必要的或多余的干扰信…

RK3568开发笔记-qt程序运行报错Failed to move cursor on screen

目录 前言 一、qt程序运行报错 二、异常解决 总结 前言 最近在进行 RK3568 平台上的 Qt 程序开发时&

使用 Docker 部署 MrDoc 在线文档管理系统

1&#xff09;MrDoc 介绍 MrDoc 简介 MrDoc 觅思文档&#xff1a;https://mrdoc.pro/ MrDoc 使用手册&#xff1a;https://doc.mrdoc.pro/p/user-guide/ MrDoc 可以创建各类私有化部署的文档应用。你可以使用它进行知识管理、构建团队文库、制作产品手册以及在线教程等。 Mr…

在Java中如何使用Lambda表达式进行函数式编程

在Java中如何使用Lambda表达式进行函数式编程 在Java中&#xff0c;使用Lambda表达式进行函数式编程主要涉及以下几个步骤&#xff1a; 理解函数式接口&#xff1a; 函数式接口是一个只有一个抽象方法的接口。Java 8引入了FunctionalInterface注解&#xff0c;用于标记这样的接…

linux安全--DNS欺骗,钓鱼网站搭建

目录 一&#xff0c;实验准备 首先让client能上网 1&#xff09;实现全网互通&#xff0c;实现全网互通过程请看 2&#xff09;SNAT源地址转换 3&#xff09;部署DHCP服务 4)配置DHCP服务 5&#xff09;启动服务 6&#xff09;安装DNS服务 7&#xff09;DNS配置 8)启动DNS…

【Python笔记-设计模式】策略模式

一、说明 策略模式是一种行为设计模式&#xff0c;它定义了一系列算法&#xff0c;将每个算法封装起来&#xff0c;并使它们可以互相替换。 (一) 解决问题 在需要根据不同情况选择不同算法或策略&#xff0c;规避不断开发新需求后&#xff0c;代码变得非常臃肿难以维护管理。…

如何将图片保存成视频(imageio、opencv和ffmpeg)

测试下来发现&#xff0c;imageio 速度比 cv2 的要慢&#xff0c;所以普通保存推荐 cv2&#xff0c;要gpu加速需要额外配置或者修改 imageio 底层也是调用的ffmpeg&#xff0c;以下是python代码 import imageio import os# 读取要保存为视频的图片 images [] for filename …