0长度数组,又称为柔性数组(flexible array)。通经常使用来实现变长数组。常见于TLV(type-length-value)的数据结构中。

在标准 C 和 C++ 中,不同意用 0 长度数组,但在
GNU C 中,却能够定义 0 长度数组(在C99之前写成长度为0,C99中能够直接不写索引)。一般会拿手冊中给的样例来说明

struct line {

         int length;

         char contents[0]; // char contents[]; //C99

}

从打印出来的结构体尺寸 sizeof (struct line) = 4 (和编译器有关,看内存对齐规则),能够看到contents[0]不占有空间(不同于字符指针类型),它存在的优点是在结构体的后面同意我们自己申请一定大小的存储空间,而不是每次都使用 MAX_SIZE 大小的结构体。通常的用法例如以下:

int this_length = 60;
struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);

thisline->length = this_length;

通过測试代码能够发现:为0长度数组分配的空间紧跟着该该结构体最后一个字段之后,并且释放结构体指针后。我们自己分配的空间也会释放(不同于有些网上的说法)。所以须要注意的是我们释放的是由某个指针指向的内存空间,而非指针,指针变量是在程序结束后回收的,所以在我们释放一段内存之后要将其置为NULL,否则还是能够訪问的,只是訪问到的都是垃圾数据。

測试代码:FlexibleArray.c
#include <stdio.h>
#include <stdlib.h> struct line {
int length;
char test;
char contents[0];//or <span style="font-family: Arial, Helvetica, sans-serif;">char contents[];</span>
}; int main(){
int i; int this_length = 60;
struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
thisline->length = this_length; printf ("thisline addr is %p\n", thisline);
printf ("thisline->length field value is %d\n",thisline->length);
printf ("thisline->length field addr is %p\n", &thisline->length);
printf ("thisline->test field addr is %p\n", &thisline->test);
printf ("thisline->contents field addr is %p\n", &thisline->contents);
printf ("thisline->contents[0] addr is %p\n", &thisline->contents[0]);
printf ("thisline->contents[0] addr is %p\n", &thisline->contents[1]); for(i=0; i<3; i++){
thisline->contents[i] = 'a' + i;
} char *p = thisline->contents;
printf("%c\n", p[2]); free(thisline);
//After free , when we access the space ,we got garbage data;
printf("%d\n", thisline->length);
printf("%c\n", p[2]); return 0;
}

执行效果:


update:2015-4-8
FlexibleArray2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h> struct line {
int length;
char test;
char contents[0];
}; int main(){
int i;
char s[20] = "Hello World.";
int that_length = 60;
struct line thisline = {5, 'A', {'a', 'b', 'c'}}; struct line *thatline = malloc(sizeof(struct line) + that_length);
thatline->length = that_length;
for(i=0; i<3; i++){
thatline->contents[i] = 'A' + i;
} char *p = thatline->contents;
printf("%c\n", p[2]); free(thatline->contents);
thatline->contents = thisline.contents;
// error: incompatible types when assigning to type ‘char[]’ from type ‘char *’
p = thatline->contents;
printf("%c\n", p[2]); return 0;
}

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdm9uemhvdWZ6/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">


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


FlexibleArray3.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h> struct line {
int length;
char test;
char contents[];
}; int main(){
struct line thisline = {5, 'A', {'a', 'b', 'c'}}; return 0;
}




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



C语言0长度数组(柔性数组)的更多相关文章

  1. 柔性数组(Redis源码学习)

    柔性数组(Redis源码学习) 1. 问题背景 在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)得到结果为8,在后续内存申请和计算中也用到.其实在工作中有遇到过这 ...

  2. (转)C语言中长度为0的数组

    前面在看Xen的源码时,遇到了一段代码,如下所示: 注意上面最后一行的代码,这里定义了一个长度为的数组,这种用法可以吗?为什么可以使用长度为0 的数组?长度为的数组到底怎么使用?……这篇文章主要针对该 ...

  3. C语言柔性数组

    结构中最后一个元素允许是未知大小的数组,这个数组就是柔性数组.但结构中的柔性数组前面必须至少一个其他成员,柔性数组成员允许结构中包含一个大小可变的数组,sizeof返回的这种结构大小不包括柔性数组的内 ...

  4. C语言柔性数组讲解

    #include<stdio.h> typedef struct _SoftArray{ int len; int array[]; }SoftArray; int main() { ; ...

  5. C语言的柔性数组的实现及应用

    c编程的时候数组长度一般都是固定好的,实际上c还能实现变长数组.其实c99中确实是有变长数组的说法,C99中通过允许结构体中的最后一个成员是长度未知的数组实现变长数组,其定义格式如下: typedef ...

  6. C语言柔性数组和动态数组

    [前言]经常看到C语言里的两个数组,总结一下. 一.柔性数组 参考:https://www.cnblogs.com/veis/p/7073076.html #include<stdio.h> ...

  7. C/C++ 中的0长数组(柔性数组)

    转自C/C++ 中的0长数组(柔性数组) 在标准C和C++中0长数组如charArray[0]是不允许使用的,因为这从语义逻辑上看,是完全没有意义的.但是,GUN中却允许使用,而且,很多时候,应用在了 ...

  8. 深入浅出C语言中的柔性数组

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

  9. (四)C语言柔性数组、指针赋值

    一.柔性数组 今天看了公司的代码,发现一个很奇怪的问题,后来自己写了类似代码,我先把代码贴出来吧. #include<stdio.h> #include<string.h> # ...

随机推荐

  1. 算法笔记_047:复数运算(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 编程实现两个复数的运算.设有两个复数 和 ,则他们的运算公式为: 要求:(1)定义一个结构体类型来描述复数. (2)复数之间的加法.减法.乘法和除法 ...

  2. 如何知道TSQL语句已经运行了多久

    如何知道TSQL语句已经运行了多久 ,) --millisecond per tick --如果datediff 函数导致溢出 把下面的millisecond改为second 毫秒改为秒 SELECT ...

  3. SQL Server Management Studio 简单使用说明

    1.对数据库中的数据生成脚本 a.选中要生成脚本的数据库右键->任务->生成脚本(如下图)->下一步->下一步->选中你想要生成的内容->下一步->完成

  4. iOS开发之UITableView的使用

    这一篇记录的是iOS开发中UITableView的使用,iOS中的UITableView跟Android中的ListView特别相似,以下用一个Demo来说明: 1.Xcode中新建projectTe ...

  5. c++实现医院检验科排班程序

    c++实现医院检验科排班程序 1.背景: 医院急诊检验科24h×7×365值班.工作人员固定.採取轮班制度.确保24h都有人值班. 本文就通过C++实现编敲代码自己主动排班,并能够转为Excel打印. ...

  6. fatal error LNK1123: 转换到 COFF 期间失败:文件无效或损坏

    问题出现背景: 原本电脑里是装着VS2015的,其使用的是.NET 4.5,当再安装VS2010之后,不能与当前的.NET平台兼容.卸载VS2015时,不会恢复.NET 4.0. l 当VS2015安 ...

  7. ie6 javascript:void(0);

    遇到过几次这种问题,现在总结一下. 代码: <a onclick="window.location.href='http://www.google.com'" href=&q ...

  8. CSS的width:100%和width:auto区别

    CSS的width:100%和width:auto区别 一.   问题 前段时间在调整树结构的时候,发现如果树的节点名称比较长的话在IE6下则不会撑开外面的元素,导致节点的名称只显示了一半,同时图标和 ...

  9. python笔记-列表和元组

    列表和元组: -可以将列表和元组当成普通的数组 -列表和元组可以保存任意类型的python对象 -通过从0开始的数字索引访问元素 -列表和元组可以存储不同类型的对象 列表和元组的区别: -列表元素使用 ...

  10. spawn-fcgi原理及源代码分析

    spawn-fcgi是一个小程序,作用是管理fast-cgi进程,功能和php-fpm类似,简单小巧,原先是属于lighttpd的一部分.后来因为使用比較广泛.所以就迁移出来作为独立项目了.本文介绍的 ...