0长度数组(柔性数组)

【C语言】柔性数组 C语言柔性数组知识 阅读详情

在日常的编程中,有时候需要在结构体中存放一个长度动态的字符串,一般的做法,是在结构体中定义一个指针成员,这个指针成员指向该字符串所在的动态内存空间,例如:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. typedef struct test    
  2. {    
  3.        int a;    
  4.        double b;    
  5.        char *p;    
  6. };  

p指向字符串。这种方法造成字符串与结构体是分离的,不利于操作。如果把字符串跟结构体直接连在一起,不是更好吗?于是,可以把代码修改为这样:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. char a[] = "hello world";  
  2. test *stpTest = (test *)malloc(sizeof(test) + strlen( a ) + 1 );  
  3. strcpy(stpTest + 1, a );  

这样一来,( char* )(stpTest + 1 )就是字符串"hello world"的地址了。这时候p成了多余的东西,可以去掉。但是,又产生了另外一个问题:老是使用( char* )((stpTest + 1 )不方便。如果能够找出一种方法,既能直接引用该字符串,又不占用结构体的空间,就完美了,符合这种条件的代码结构应该是一个非对象的符号地址,在结构体的尾部放置一个0长度的数组是一个绝妙的解决方案。不过,C/C++标准规定不能定义长度为0的数组,因此,有些编译器就把0长度的数组成员作为自己的非标准扩展。
在讲述柔性数组成员之前,首先要介绍一下不完整类型incomplete type)。不完整类型是这样一种类型,它缺乏足够的信息例如长度去描述一个完整的对象,

它的出现反映了C程序员对精炼代码的极致追求,这种代码结构产生于对动态结构体的需求。

鉴于这种代码结构所产生的重要作用,C99甚至把它收入了标准中。C99使用不完整类型实现柔性数组成员,在C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组(flexible array)成员(也叫伸缩性数组成员),但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组。柔性数组成员只作为一个符号地址存在,而且必须是结构体的最后一个成员,sizeof 返回的这种结构大小不包括柔性数组的内存。柔性数组成员不仅可以用于字符数组,还可以是元素为其它类型的数组。包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。柔性数组的使用请看下面的例子:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. typedef struct test  
  2. {  
  3.     int a;  
  4.     double b;  
  5.     char c[0];  
  6. };  

有些编译器会报错无法编译可以改成:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. typedef struct test  
  2. {  
  3.     int a;  
  4.     double b;  
  5.     char c[];  
  6. };  

通过如下表达式给结构体分配内存:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. test *stpTest = (test *)malloc(sizeof(test)+100*sizeof(char));  

c就是一个柔性数组成员,如果把stpTest指向的动态分配内存看作一个整体,c就是一个长度可以动态变化的结构体成员,柔性一词来源于此。c的长度为0,因此它不占用test的空间,同时stpTest->c就是“hello world”的首地址,不需要再使用( char * )( stpTest + 1 )这么丑陋的代码了。那个0个元素的数组没有占用空间,而后我们可以进行变长操作了。这样我们为结构体指针c分配了一块内存。用stpTest->c[n]就能简单地访问可变长元素。

当然,上面既然用malloc 函数分配了内存,肯定就需要用free 函数来释放内存:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. free(stpTest);  

应当尽量使用标准形式,在非C99的场合,可以使用指针方法。需要说明的是:C89不支持这种东西,C99把它作为一种特例加入了标准。但是,C99所支持的是incomplete type,而不是zero array,形同int a[0];这种形式是非法的,C99 支持的形式是形同int a[];只不过有些编译器把int a[0];作为非标准扩展来支持,而且在C99 发布之前已经有了这种非标准扩展了,C99 发布之后,有些编译器把两者合而为一了。


另外:

测试代码:FlexibleArray.c
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. struct line {  
  5.          int length;  
  6.          char test;  
  7.          char contents[0]; 
  8.     };  
  9.   
  10. int main(){  
  11.     int i;  
  12.       
  13.     int this_length = 60;  
  14.     struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);  
  15.     thisline->length = this_length;  
  16.   
  17.     printf ("thisline addr is %p\n", thisline);  
  18.     printf ("thisline->length field value is %d\n",thisline->length);  
  19.     printf ("thisline->length field addr is %p\n", &thisline->length);  
  20.     printf ("thisline->test field addr is %p\n", &thisline->test);  
  21.     printf ("thisline->contents field addr is %p\n", &thisline->contents);  
  22.     printf ("thisline->contents[0] addr is %p\n", &thisline->contents[0]);  
  23.     printf ("thisline->contents[0] addr is %p\n", &thisline->contents[1]);  
  24.   
  25.     for(i=0; i<3; i++){  
  26.         thisline->contents[i] = 'a' + i;  
  27.     }  
  28.       
  29.     char *p = thisline->contents;  
  30.     printf("%c\n", p[2]);  
  31.       
  32.     free(thisline);  
  33.     //After free , when we access the space ,we got garbage data;  
  34.     printf("%d\n", thisline->length);  
  35.     printf("%c\n", p[2]);  
  36.   
  37.     return 0;  
  38. }  

运行效果:

update:2015-4-8
FlexibleArray2.c
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. struct line {  
  6.          int length;  
  7.          char test;  
  8.          char contents[0];  
  9.     };  
  10.   
  11. int main(){  
  12.     int i;  
  13.     char s[20] = "Hello World.";  
  14.     int that_length = 60;  
  15.     struct line thisline = {5, 'A', {'a', 'b', 'c'}};  
  16.   
  17.     struct line *thatline = malloc(sizeof(struct line) + that_length);  
  18.     thatline->length = that_length;  
  19.     for(i=0; i<3; i++){  
  20.         thatline->contents[i] = 'A' + i;  
  21.     }  
  22.   
  23.   
  24.     char *p = thatline->contents;  
  25.     printf("%c\n", p[2]);  
  26.   
  27.     free(thatline->contents);  
  28.    thatline->contents = thisline.contents;  
  29. // error: incompatible types when assigning to type ‘char[]’ from type ‘char *’  
  30.     p = thatline->contents;  
  31.    printf("%c\n", p[2]);  
  32.   
  33.     return 0;  
  34. }  


可以看到根本无法修改一个实例中contents的指向,所以占用的是完整的内存区间,不能指向单独的地址空间。

FlexibleArray3.c
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. struct line {  
  6.          int length;  
  7.          char test;  
  8.          char contents[];  
  9.     };  
  10.   
  11. int main(){  
  12.     struct line thisline = {5, 'A', {'a', 'b', 'c'}};  
  13.   
  14.     return 0;  
  15. }  


可以看到严格的弹性数组和长度0的数组还是有区别的,这里就不能使用静态初始化,只能像FlexibleArray1.c中那样操作

C语言0长度数组(可变数组/柔性数组) / 0长度数组int len;// 定长数组int len;// 指针数组int len;char *data;// 0长度数组 占用-开辟-销毁/// 占用/// 开辟= NULL)/// 销毁// 定长数组 占用-开辟-销毁/// 占用/// 开辟= NULL)/// 销毁// 指针数组 占用-开辟-销毁/// 占用/// 开辟= NULL)= NULL)/// 销毁。 阅读详情

相关推荐

qcom bypass node介绍

介绍qcom bypass node,以及如何让其生效

haodada1226的博客 2043

详解柔性数组

本文详解了柔性数组(flexible array),具体包括:什么是柔性数组、如何计算包含柔性数组成员的结构体的大小、柔性数组的使用以及柔性数组的优点。

melonyzzZ的博客 2226

VSCode + Latex 配置

1. 安装VSCode VSCode下载 next,next就安装好了。 2. 配置VSCode 2.1 安装LaTeX Workshop插件 install,安装LaTeX Workshop插件 2.2 修改 user setting 点击左下角,进入用户设置 点击上图标记的部分,选择 打开settings.json 具体配置文件如下: { "latex-workshop.la...

一只特立独行的猪 10万+

柔性数组详解

柔性数组也称为变长数组,是一种动态数组的实现方式。与普通数组不同的是,柔性数组在定义时不需要明确指定数组大小,在程序运行时可以动态地分配和扩展数组大小。 这种开辟的内存空间并不是紧挨着后面开的,而是随便找的一块内存空间,这就导致我们需要多次释放内存。 而柔性数组是紧挨着结构体后开辟的空间,可以直接一次性的释放

qq_64818885的博客 2802

实战复盘:一次绕过WAF的EDUSRC SQL注入漏洞挖掘

本文详细复盘了一次针对教育行业网站的SQL注入漏洞挖掘实战。通过手动信息收集发现可疑点,并利用‘+’号替换空格等技巧,成功绕过WAF(Web应用防火墙)的拦截。文章逐步演示了从判断注入点到手工获取数据结构、最终解密进入后台的完整过程,并总结了手工测试的优势及高级绕过思路,强调了在EDUSRC等授权范围内进行安全测试的重要性。

weixin_28622215的博客 191

西门子S7-200 SMART与施耐德ATV变频器Modbus通讯实战:从接线到稳定运行的完整指南

本文详细介绍了西门子S7-200 SMART PLC与施耐德ATV变频器之间实现稳定Modbus通讯的完整实战指南。内容涵盖从硬件接线、参数配置、PLC程序编写到触摸屏设计的全流程,并分享了提升通讯稳定性的关键技巧和常见故障排查方法,助力工业自动化系统可靠运行。

kkk56的博客 1106

你可能没听过的数组-----柔性数组

一、简述 柔性数组其实是结构体中的最后一个数组未说明大小,且结构体中至少包含一个以上其他类型,如 #include<stdio.h> struct hei { int zeng; char shi; int arr[];//或者int arr[0]; }ma; int main() { struct hei ma; return 0 } 二、具体使用 #include<stdio.h> #include<stdlib.h>//#inclu

weixin_60719453的博客 2768

将Matlab程序打包成.exe独立可执行程序

将Matlab程序打包成.exe独立可执行程序,在未安装Matlab的电脑上也能运行Matlab程序。

简简单单的学习笔记,致力于帮助更多前进路上的朋友~ 5万+

柔性数组(详讲版)

这样可以简化内存管理,减少分配和释放内存的次数,提高程序的效率。由于柔性数组的长度可以在运行时根据实际需求进行调整,所以可以很方便地适应不同大小的数据。在使用柔性数组时,需要我们手动开辟内存空间,并且对内存进行调整,我们用mallohenc进行内存的开辟,使用realloc对内存进行调整扩充。柔性数组即数组大小待定的数组,在 C 语言中可以在结构体的最后一个元素使用长度为 0 的数组来实现。以下两段代码所要展现的效果是一样的,不过他们有不同的思路,下面来看。⭐有关柔性数组中自定义类型的博文。

Hello_shuo的博客 1912

TC3XX - MCAL知识点(九):PWM EB-tresos配置说明及代码浅析

脉冲宽度调制(PWM)驱动器负责提供与AUTOSAR指定的PWM信号生成相关的标准服务。PWM通道的底层定时器驱动是GTM (TOM或ATOM片)或CCU6 (T12或T13片)定时器通道。软硬件匹配关系如下:PWM直接引用的是GTM与CCU6模块,然后GTM与CCU6再关联到Port的,根据软硬件匹配关系,也能调用中断来使用,本例子没使用中断。CCU6是一个高分辨率的16位捕获和比较单元,具有特定的应用模式,主要用于交流驱动控制。特殊的工作模式支持控制无刷直流电机使用霍尔传感器或反电动势检测。

梦想技术家 2887

使用VNA(Vector Network Analyzer)对S参数进行去嵌(一)

传统上,RF和微波组件被设计成具有同轴接口的封装。通过连接一系列这些单独的同轴设备,可以容易地制造复杂的系统。使用使用类似同轴接口的标准测试设备可以很容易地测量这些部件和系统的性能。然而,现代系统需要更高水平的组件集成、更低的功耗和更低的制造成本。射频组件正在迅速从使用昂贵同轴接口的设计转向使用印刷电路板和表面贴装技术(SMT)的设计。传统的同轴接口甚至可以从最终产品中取消。这就给设计者留下了用需要同轴接口的测试设备测量这些射频和微波组件性能的问题。解决方案是使用连接同轴和非同轴传输线的测试夹具。

小孟同学的博客 1万+

C语言0长度数组(柔性数组)

C语言0长度数组(柔性数组)                                                                                0长度数组,又称为柔性数组(flexible array),通常用来实现变长数组,常见于TLV(type-length-value)的数据结构中。在标准 C 和 C++ 中,不允许用 0 长度数组,但在

博观约取 3219

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

C语言:0长度数组/可变数组/柔性数组

C语言:0长度数组/可变数组/柔性数组1. 0长度数组1.1 代码例子1.2 什么是0长度数组(可变数组/柔性数组)?1.3 用途1.4 用法1.5 优点1.6 缺点1.7 重点:数组名仅仅是一个符号1.8 GNU Document中 变长数组的支持2. 代码测试例(0长度的数组,定长数组,指针数组)3. 参考: 1. 0长度数组 C语言:0长度数组又叫做:可变数组或者柔性数组 1.1 代码例子 struct ZeroBuffer { int len; char acData[0]; //这里的0长结构

哈尼的博客 663

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

结构体中最后一个成员为 0 或 1 长度数组 柔性数组成员 的用法

结构体中最后一个成员为 0 或 1 长度数组 柔性数组成员 的用法

hddryjv的博客 407

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

柔性数组(0长度数组)

文章目录什么是柔性数组?柔性数组的特点柔性数组的使用模拟实现柔性数组的功能柔性数组的优势 什么是柔性数组? 柔性数组这个概念相信大多数人博友都没有听说过,但是它确实存在。 在C99中,结构(结构体)的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员。 比如: struct S { int n; int arr[];//柔性数组成员 }; 或者是: struct S { int n; int arr[0];//柔性数组成员 }; 柔性数组的特点 一、结构中柔性数组成员前面必须至少有一个其他成

2021dragon的博客 1506

c语言局部数组长度,C语言0长度数组(柔性数组)

0长度数组,又称为柔性数组(flexible array)。通经常使用来实现变长数组。常见于TLV(type-length-value)的数据结构中。在标准 C 和 C++ 中,不同意用 0 长度数组,但在GNU C 中,却能够定义 0 长度数组(在C99之前写成长度为0,C99中能够直接不写索引)。一般会拿手冊中给的样例来说明structline{intlength;charconten...

weixin_28819153的博客 269

结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法

结构体中最后一个成员为[0]长度数组的用法:这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:(1)、不需要初始化,数组名直接就是所在的偏移;(2)、不占任何空间,指针需要占用int长度空间,空数组不占任何空间。“这个数组不占用任何内存”,意味着这样的结构节省空间;“该数组的内存地址就和它后面的元素地址相同”,意味着无需初始化,数组名就是后面元素的地址,直接就能当指针使...

SurpassLi的专栏 36

柔性数组&长度为0的数组

可以看出它们空间分配的差别:使用字符串指针的方式,需先为 Node 结构体分配一块内存空间,再为 Node 的 arr 变量分配内存空间,这样两次分配的内存是不连续的;在释放时使用字符串指针的方式也需要多次释放,使用 0 数组一次释放就行了。柔性数组是引入的一个新特性,允许在定义结构体时,最后一个成员为一个空数组,并且这样的结构体至少包含一个其他类型的成员。我们可以在结构体的末尾放入一个长度为 0 的数组(注:如果不是末尾,编码器则会报错),从输出结果可以看到这个长度为 0 的数组没有占用空间。

好好学习,天天向上 207

【柔性数组】0长度数组,可变数组

在c99标准中,引入了“柔性数组”的概念;即在c99中,结构体的最后一个成员可以是一个未知大小的数组(没有长度的数组);这个数组就叫做**【柔性数组】成员**;柔性数组可以根据使用者的需求进行malloc,确保数组在使用中能保证足够且不过多浪费空间。

小侯宝的博客 308

C语言0长度数组(可变数组/柔性数组)详解

版权声明:本文转载自 @ http://blog.youkuaiyun.com/gatieme https://blog.youkuaiyun.com/gatieme/article/details/64131322 优快云 GitHub C语言0长度数组(可变...

xingzhe12345的博客 1272

C语言 0长度数组/柔性数组

零长度数组就是长度为0的数组。ANSIC标准规定定义一个数组时,数组的长度必须是一个常数,即数组的长度在编译的时候是确定的。在ANSIC中定义一个数组的方法如下类型数组名[数组元素个数];例如C99新标准规定可以定义一个变长数组。C语言的变长数组)intlen;也就是说,数组的长度在编译时是未确定的,在程序运行的时候才确定,甚至可以由用户指定大小。比如,我们可以定义一个数组,然后在程序运行时才指定这个数组的大小,还可以通过输入数据来初始化数组。.........

a只如初见的博客 2974

柔性数组成员 长度为0的数组

柔性数组成员 http://blog.youkuaiyun.com/code_crash/article/details/4854939 在讲述柔性数组成员之前,首先要介绍一下不完整类型(incomplete type)。不完整类型是这样一种类型,它缺乏足够的信息例如长度去描述

jinchengzhou的专栏 386
上一篇: select、poll、epoll之间的区别总结[整理]
下一篇: __stdcall,__cdecl,__pascal,__fastcall的区别
big_bit
博客等级 码龄11年 67粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值