码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【Linux C小技巧】零长度数组的使用


    本期主题:
    讲清Linux C的零长度数组使用,内容包括:

    1. 零长度数组是什么原理
    2. 为什么要使用零长度数组
    3. 与指针的差异

    往期链接:

    • 数据结构系列——先进先出队列queue
    • 数据结构系列——栈 stack
    • Linux内核链表

    目录

    • 0.前言
    • 1.零长度数组原理
    • 2.零长度数组特点1:不占空间
    • 3.零长度数组特点2:分配的空间可以连续


    0.前言

    有时候我们在看代码时,会有这种结构体,定义了一个数组长度为0的数组,如下面代码,我初次看见时非常疑惑,那么零长度数组的意义是什么呢?

    typedef struct {
    	int a;
    	uint8_t c[0];
    } test_a;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.零长度数组原理

    1. 长度为0的数组在标准c和c++中是不允许的,如果使用长度为0的数组,编译时会产生错误,提示数组长度不能为0
    2. 但在GNU C中,这种用法却是合法的。它的最典型的用法就是位于数组中的最后一项,如上面所示,这样做主要是为了方便内存缓冲区的管理

    2.零长度数组特点1:不占空间

    看下面这段代码:设计一个包含零长度数组的结构体test_a,还有一个包含指针的结构体test_c

    #include 
    #include 
    #include 
    
    typedef struct {
    	int a;
    	uint8_t c[0];
    } test_a;
    
    typedef struct {
    	int b;
    } test_b;
    
    /*这里使用packed,是因为我编译环境是64位
     *如果不用packed,担心影响大家判断
     */
    typedef struct {
    	int 	c;
    	uint8_t *ptr;
    } __attribute__ ((packed)) test_c;
    
    int main(void)
    {
    	test_a a;
    	test_b b;
    	test_c c;
    	printf("sizeof test_a: %ld, sizeof test_b: %ld, sizeof test_c: %ld\n",
    			sizeof(a), sizeof(b), sizeof(c));
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    测试结果:

    $ ./a.out
    sizeof test_a: 4, sizeof test_b: 4, sizeof test_c: 12
    
    • 1
    • 2

    结论:

    可以看出,零长度数组是不占用空间的,这是它优于指针的一个点

    3.零长度数组特点2:分配的空间可以连续

    设想一个这样的场景,需要设计发送消息的代码,消息包括消息头和payload字段,有两种设计方式:

    typedef struct {
    	msg_head_t msg_head;
    	uint8_t    data[0];
    } msg_t;
    
    typedef struct {
    	msg_head_t msg_head;
    	uint8_t    *data;
    } msg_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    你觉得哪种更好?

    从底层发送接口的角度来考虑,设计函数时,有一个消息的整体指针作为入参就可以了,所以当然是第一种数据连续的底层更好适配。这是零长度数组的第二个特点,比指针更为灵活,空间连续
    看测试代码:

    #include 
    #include 
    #include 
    #include 
    
    typedef struct _msg_a {
    	int 	len;
    	uint8_t data[0];
    } msg_a_t;
    
    typedef struct _msg_b {
    	int 	len;
    	uint8_t *data;
    } msg_b_t;
    
    int main(void)
    {
    	int data_len = 10;
    	msg_a_t *ptr_msg_a = (msg_a_t *)malloc(sizeof(msg_a_t) + data_len);
    	msg_b_t *ptr_msg_b = (msg_b_t *)malloc(sizeof(msg_b_t));
    	ptr_msg_b->data = malloc(data_len);
    	
    	printf("a: %p, a_data: %p, b: %p, b_data: %p\n",
    			ptr_msg_a, ptr_msg_a->data, ptr_msg_b, ptr_msg_b->data);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    结果:

    $ ./a.out
    a: 0x560958fb1260, a_data: 0x560958fb1264, b: 0x560958fb1280, b_data: 0x560958fb12a0
    
    • 1
    • 2

    能看出零长度数组确实是连续空间,符合预期。

    参考自 嵌入式C语言自我修养 05:零长度数组

  • 相关阅读:
    MySQL 字段值按照分隔符拆分成列(行转列)
    JavaSE进阶21天---第二十天---JavaSE(​​日志、logback日志、添加模板、类加载器、ressources文件夹)
    Qt之元对象metaObject
    SQLmap 结合本地dnslog实现注入
    利用phpstudy(小皮面板)配置本地PHP开发环境的记录
    回归模型原理总结及代码实现
    Spring Boot 中使用 Micrometer 进行度量和监控
    【强化学习论文合集】AAAI-2022 强化学习论文 | 2022年合集(二)
    力扣 430. 扁平化多级双向链表
    macbook安装Anaconda3,TensorFlow,Keras
  • 原文地址:https://blog.csdn.net/weixin_37620587/article/details/132915468
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号