C语言柔性数组讲解

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

int main()
{
    int len = 10;

    printf("The struct‘s size is %d\n",sizeof(SoftArray));
}

我们可以看出,_SoftArray结构体的大小是4,显然,在32位操作系统下一个int型变量大小刚好为4,也就说结构体中的数组没有占用内存。为什么会没有占用内

存,我们平时用数组时不时都要明确指明数组大小的吗?但这里却可以编译通过呢?这就是我们常说的动态数组,也就是柔性数组。

先不要乱,让我们再看一段代码

#include<stdio.h>
#include<malloc.h>

typedef struct _SoftArray{
    int len;
    int array[];
}SoftArray;

int main()
{
    int len = 10;

    SoftArray *p=(SoftArray*)malloc(sizeof(SoftArray) + sizeof(int)*len);
    printf("After the malloc function the struct‘s size is %d\n”,sizeof(SoftArray));

    return 0;
}

是不是有点奇怪,为什么申请了内存后结构体大小还是4呢?原因是动态申请的内存只是申请给数组拓展所用,从上个程序我们可以看出结构体的大小在创建时已经

确定了,array明确来说不算是结构体成员,只是挂羊头卖狗肉而已。

下面我们来看看关于柔性数组的资料:

1、什么是柔性数组?

柔性数组既数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建柔性数组。

2、柔性数组有什么用途 ?

它的主要用途是为了满足需要变长度的结构体,为了解决使用数组时内存的冗余和数组的越界问题。

3、用法 :在一个结构体的最后 ,申明一个长度为空的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名

本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们

可以进行动态分配,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!

对于柔性数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:

typedef struct _SoftArray

{

Int len;

int array[];

}SoftArray;

这样的变长数组常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量,比如我要发送1024字节的数据,如果用定长包,假设定长包的长度为2048,就

会浪费1024个字节的空间,也会造成不必要的流量浪费。

4、举个简单是实例

#include<stdio.h>
#include<malloc.h>
typedef struct _SoftArray{
int len;
int array[];
}SoftArray;
int main()
{
    int len=10,i=0;

    SoftArray *p=(SoftArray*)malloc(sizeof(SoftArray)+sizeof(int)*len);
    p->len=len;

    for(i=0;i<p->len;i++)
   {
        p->array[i]=i+1;
    }
    for(i=0;i<p->len;i++)
   {
        printf("%d\n",p->array[i]);
    }

    free(p);

    return 0;
}    

这代码的作用是用柔性数组动态创建数组并输出数组内容,这里我就直接解释解释这两句代码

   SoftArray* p = (SoftArray*)malloc(sizeof(SoftArray) + sizeof(int) *10);

   p->len = 10;

第一句,主要是根据你要定义的数组长度和数据类型以及柔性数组本身的大小来开辟一块内存空间给柔性数组,第二个是定义len的长度,便于确定循环打印输出

是循环的次数。

5、运行错误的解决

#include<stdio.h>
#include<malloc.h>
typedef struct _SoftArray{
int len;
int array[];
}SoftArray;
int main()
{
    int len=10,i=0;

    SoftArray *p=(SoftArray*)malloc(sizeof(SoftArray)+sizeof(int)*len);
    p->len=len;

    for(i=0;i<11;i++)
   {
        p->array[i]=i+1;
    }
    for(i=0;i<11;i++)
   {
        printf("%d\n",p->array[i]);
    }

    free(p);

    return 0;
} 

所谓初生牛犊不怕死,我在写柔性数组程序时,为了做了个大胆的尝试,那就是我在上一个代码中申请内存时申请了10,但赋值时我把大小写了11,问题出现了,

话不多说,直接上图

我当时不知道是什么问题,我也蒙了~---~

但我又做出了一个伟大的决定,我把free(p)注释掉了,结果11成功打印出来了。我当时真是One Face mengbi。

后来才发现其实是因为在动态分配内存的时候往往分配的是一个连续的地址,这一点从可以使用*[a+3]来取值就能够知道。

因此,在动态分配的时候,会在数组界限外加一个用来标识数组范围的标志,例如a数组,就会在array[-1]和array[11]有两个标志,如果我们在这两个位置赋值,赋

值和调用时并不会出错,而是在freed掉array申请的内存时出错,错误的名称就是“DAMAGE: before Normal block”和“DAMAGE: after Normal block”。一般是后者居

多。因此,当你遇见这个错误的时候,记得去检查一下自己数组的赋值吧。

6、注意说明

在定义这个结构体的时候,模子的大小就C89不支持这种东西,C99把它作为一种特例加入了标准。

但是,C99所支持的是 incomplete type,而不是 zero array,形同 int item[0];这种形式是非法的,C99支持的形式是形同 int item[];只不过有些编译器把 int item[0];作

为非标准扩展来支持,而且在C99发布之前已经有了这种非标准扩展了,C99发布之后,有些编译器把两者合而为一了。当然,上面既然用 malloc函数分配了内存,

肯定就需要用 free函数来释放内存:free(p);这两个函数是一对CP,就好像fopen()和fclose();记住不要乱拆CP,拆CP是有风险的哦。

最后再送大家一个代码玩玩:

 1 #include<stdio.h>
 2 #include<malloc.h>
 3 typedef struct _SoftArray{
 4     int len;
 5     int array[];
 6 }SoftArray;
 7
 8 //打印输出斐波那契数列
 9 void printfln(SoftArray *p,int len)
10 {
11     int i;
12
13     for(i=0;i<len;i++)        //循环进行打印输出
14     {
15         printf("%d\n",p->array[i]);
16     }
17 }
18
19 //动态生成斐波那契数列
20 void create(int len)
21 {
22     int i;
23
24     SoftArray * p=(SoftArray*)malloc(sizeof(SoftArray)+sizeof(int)*len);    //声明结构体指针p,动态申请内存,大小为结构体大小+10个int型大小
25
26     for(i=0;i<len;i++)        //循环进行数组赋值
27     {
28         if( i <= 1 )
29         {
30             p->array[i] = 1;
31         }else if( i >= 2 )
32         {
33             p->array[i] = p->array[i-1] + p->array[i-2];
34         }else
35         {
36             printf("DAMAGE: before Normal block or after Normal block");
37             return (-1);
38         }
39
40     }
41     printfln(p,len);
42
43     free(p);
44 }
45
46 //主函数
47 int main()
48 {
49     int i=0;
50     int len;
51
52     printf("请输入生成斐波那契数列的行数:");
53     scanf("%d",&len);
54
55     create(len);
56
57     return 0;
58 }
时间: 2024-10-20 09:17:18

C语言柔性数组讲解的相关文章

C语言柔性数组

柔性数组:数组大小待定的数组.C语言中结构体最后一个元素可以是大小未知的数组.C语言可以由结构体产生柔性数组 柔性数组的结构如何只能堆上生成 柔性数组是C99的扩展,简而言之就是一个在struct结构里的标识占位符(不占结构struct的空间). #include <stdio.h> #include <malloc.h> typedef struct _soft_array { int len; int array[]; }SoftArray; int main() { int

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

[前言]经常看到C语言里的两个数组,总结一下. 一.柔性数组 参考:https://www.cnblogs.com/veis/p/7073076.html #include<stdio.h> typedef struct _SoftArray{ int len; int array[]; }SoftArray; int main() { int len = 10; printf("The struct's size is %d\n",sizeof(SoftArray));

c语言关键字-struct,union,enum及柔性数组

一.struct关键字与柔性数组 c语言中的struct可以看做变量的集合,struct中的每个数据成员都有独立的存储空间 柔性数组:柔性数组在C99中也称之为伸缩型数组,是C99的扩展,简言之就是struct结构里的标识占位符(不占用struct的空间),柔性数组的结构只能在堆上生成. 声明柔性数组的规则 柔性数组成员必须为结构(struct)中的最后一个成员 结构中至少有一个其他成员 柔性数组就像普通数组一样被声明,除了它的方括号内为空 1 struct softarry 2 { 3 int

程序猿之---C语言细节29(#define宏大小、空结构体大小、柔性数组不知道你见过没)

主要内容:#define宏大小.空结构体大小.柔性数组 一.#define宏大小 见例子 二.空结构体大小 根编译器有关 三.柔性数组 不常用,可看看 #include <stdio.h> #define N 4 #define STR "abcd" int main() { struct student { }stu; printf("N = %d\n", sizeof(N)); printf("num 5 memery = %d\n&quo

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

0长度数组,又称为柔性数组(flexible array),通常用来实现变长数组,常见于TLV(type-length-value)的数据结构中.在标准 C 和 C++ 中,不允许用 0 长度数组,但在 GNU C 中,却可以定义 0 长度数组.通常会拿手册中给的例子来说明 struct line { int length; char contents[0]; } 从打印出来的结构体尺寸 sizeof (struct line) = 4 (和编译器有关,看内存对齐规则),可以看到contents

C语言变长消息定义:柔性数组

在游戏前后端交换的过程中,经常会用到变成的消息体,因为有的内容的大小是位置的,例如一条微博,微博的内容大小是未知的. 一般的做法是定义一个char*类型的指针,然后指定其长度,代码如下: typedef struct{ unsigned len; char* pData; }Msg; 使用的时候是这样的: char str[] = "hello world!"; unsigned len = sizeof(str); Msg* m = (Msg*)malloc(sizeof(Msg)+

柔性数组成员 (flexible array member)-C99-ZZ

学习flexible array member是因为阅读Redis源码遇到的,sds.h中一开始就用到了. ============================================================================================== 在讲述柔性数组成员之前,首先要介绍一下不完整类型(incomplete type).不完整类型是这样一种类型,它缺乏足够的信息例如长度去描述一个完整的对象. 6.2.5 Types incomplete

C柔性数组

柔性数组成员 柔性数组 1.允许结构中包含一个大小可变的数组,sizeof返回的这种结构大小不包括柔性数组的内存. 2.包含柔性数组成员的结构要使用malloc()函数进行内存的动态分配.分配的内存大于结构体的大小. 3.柔性数组的定义 typedef strcut type { int i; int a[]; }type_a; 4.type_a *p=(type_a *)malloc(sizeof(type_a)+100*sizeof(int)); 5.p->a[n]直接访问数组. 6.fre

线性表之顺序存储结构(C语言动态数组实现)

线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链式存储结构:是用一段一段连续的内存空间存储表中每一行的数据,段与段之间通过一个引用(指针)相互连接来,形成一个链式的存储结构 看到顺序存储结构的图示,我们可能会马上联想到C语言的数组.是的,数组就是一种典型的顺序存储数据结构.下面我通过一个实例,来实现对顺序存储结构中的数据增.删.改.查的操作. 首