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

news2024/12/23 14:38:37

文章目录

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

摘要

本文先介绍柔性数组成员(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 buffer
  struct 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 buffer
  struct 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.coloradmin.cn/o/1487301.html

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

相关文章

有趣的CSS - 一串乱码

大家好&#xff0c;我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;今天分享的是通过 css 来实现一段不停变化的 bug 乱码效果。 《有趣的css》系列最新实例通过公众号「设计师工作日常」发布。 目录 整体效果核心代码html 代码css 部分代码 完整代码如下html 页面…

AMDGPU KFD Test 编译使用

ROCT-Thunk-Interface是一个用于在ROCm软件堆栈中提供设备无关性的层。它是ROCm的一部分&#xff0c;允许不同的硬件平台&#xff08;如AMD GPU和Intel CPU&#xff09;使用相同的API进行计算。 要安装ROCT-Thunk-Interface&#xff0c;首先需要创建一个新的目录&#xff0c;并…

开源免费的文件互传工具,LocalSend软件推荐

怎么把手机里的文件传到电脑或电脑的文件传到手机&#xff1f; 在日常生活和工作中&#xff0c;我们经常需要在不同的设备间传输文件&#xff0c;比如照片、视频、文档等。如果你使用是统一的苹果设备Airdrop可以非常方便的共享文件&#xff0c;但是如果你要在不同操作系统的设…

css 鼠标移入放大的效果

效果 HTML <div class"img-wrap"><img class"img-item" src"../assets/1.png" alt"" srcset""></div> CSS <style lang"less" scoped> .img-wrap {/* 超出隐藏 */overflow: hidden;.img-…

开发环境热部署

为什么需要热部署 在实际开发中&#xff0c;经常要修改代码&#xff0c;然后重启服务&#xff0c;再验证代码是否生效。对于开发场景&#xff0c;随着项目的演进&#xff0c;微服务越来越多&#xff0c;等待重启的时间也会越来越多&#xff1b;对于联调场景&#xff0c;对一处…

代码随想录Day66 | 图的DFS与BFS

代码随想录Day66 | 图的DFS与BFS DFS797.所有可能的路径无向图和有向图的处理 BFS200.岛屿数量 DFS 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a; 状态 本质上就是回溯算法。 void dfs(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本节点所连接的…

for循环语句

语法格式&#xff1a; for (表达式1; 表达式2; 表达式3) { 若干语句;//循环体 } 执行规则 STEP1&#xff1a;计算“表达式1” &#xff0c;初始化。 STEP2&#xff1a; 判断“表达式2”的值&#xff0c;若 “表达式2”的值为true&#xff0c;则进行 STEP2&#xff0c;否则进行…

DevStack 基于 Ubuntu 部署 OpenStack

Devstack 简介 DevStack 是一系列可扩展的脚本&#xff0c;用于基于 git master 的最新版本快速调出完整的 OpenStack 环境。devstack 以交互方式用作开发环境和 OpenStack 项目大部分功能测试的基础。 devstack 透过执行 stack.sh 脚本&#xff0c;搭建 openstack 环境&…

ChatGPT最新功能“Text To Speech (TTS,文本转语音)”详细解读!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

32单片机基础:PWM驱动舵机,直流电机

PWM驱动舵机 接线图如上图所示。注意&#xff0c;舵机的5V 线不能接到面包板上的正极&#xff0c;面包板上的正极只有3.3V,是STM32提供的&#xff0c;所以要接到STLINK的5V, 我们如何驱动舵机呢&#xff1f;由之前我们介绍原理知道&#xff0c;要输出如下图对应的PWM波形才行…

【FPGA/IC】CRC电路的Verilog实现

前言 在通信过程中由于存在各种各样的干扰因素&#xff0c;可能会导致发送的信息与接收的信息不一致&#xff0c;比如发送数据为 1010_1010&#xff0c;传输过程中由于某些干扰&#xff0c;导致接收方接收的数据却成了0110_1010。为了保证数据传输的正确性&#xff0c;工程师们…

CentOS配网报错:network is unreachable

常用命令&#xff1a; 打开&#xff1a; cd /etc/sysconfig/network-scripts/ 修改&#xff1a; vim ifcfg-ens33 打开修改&#xff1a; vim /etc/sysconfig/network-scripts/ifcfg-ens33 保存&#xff1a; 方法1&#xff1a;ESCZZ&#xff08;Z要大写&#xff09; 方…

递归实现n的k次方(C语言)

编写一个函数实现n的k次方&#xff0c;使用递归实现。 下面来说一下思路 5的3次方&#xff1a;就是5*(5的3-1次方) 7的4次方&#xff1a;就是7*&#xff08;7的4-1次方&#xff09; 以此类推 n的k次方就是&#xff1a;n* n的&#xff08;k-1&#xff09;次方 int Func(int n,…

C++基于多设计模式下的同步异步日志系统day4

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C基于多设计模式下的同步&异步日志系统 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 只要内容主要实现了同步日志消息…

“智农”-农业物联网可视化

大棚可视化|设施农业可视化|农业元宇宙|农业数字孪生|大棚物联网|大棚数字孪生|农业一体化管控平台|智慧农业可视化|智农|农业物联网可视化|农业物联网数字孪生|智慧农业|大棚三维可视化|智慧大棚可视化|智慧大棚|农业智慧园区|数字农业|数字大棚|农业大脑|智慧牧业数字孪生|智…

072:vue+cesium 实现下雪效果

第072个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中实现下雪效果,这里使用着色器来实现实例特效。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共120行)着色代码实现心得:专栏目标示例效果

2022NOC大赛原创未来赛道小学低年级组图形化真题加解析

这篇文档是一份未来小学低年级组图形化真题加解析,主要面向小学生进行考试。考试内容主要包括图形化思维、数学运算和阅读理解等方面。 图形化思维是近年来数学教育中备受关注的领域,通过将抽象的概念转化为具体的形象,帮助学习者更好地理解和掌握数学知识。因此,在这个考试…

STM32-BKP备份寄存器和RTC时钟

BKP介绍 BKP(Bckup Registers&#xff09;备份寄存器 备份寄存器是42个16位的寄存器&#xff0c;可用来存储84个字节的用户应用程序数据。他们处在备份域里&#xff0c;当VDD电源被切断&#xff0c;他们仍然由VBAT&#xff08;备用电池电源&#xff09;维持供电。当系统在待机…

011集——vba获取CAD图中图元类名objectname

在CAD中&#xff0c;通过快捷键PL&#xff08;即POLYLINE命令&#xff09;绘制的线属于AcDbPolyline。AcDbPolyline也被称为LWPOLYLINE&#xff0c;即简单Polyline&#xff0c;它所包含的对象在本身内部。 此外&#xff0c;CAD中还有另一种二维多段线对象&#xff0c;称为AcDb2…

Vue开发实例(十一)用户列表的实现与操作

用户列表的实现与操作 一、创建用户页面和路由二、表格优化1、表头自定义2、表格滚动3、加入数据索引4、利用插槽自定义显示 三、功能1、查询功能3、增加4、删除5、修改 一、创建用户页面和路由 创建用户页面 在 src/components/Main 下创建文件夹user&#xff0c;创建文件Us…