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呢?緣由是動態申請的內存只是申請給數組拓展所用,從上個程序咱們能夠看出結構體的大小在建立時已經spa

肯定了,array明確來講不算是結構體成員,只是掛羊頭賣狗肉而已。操作系統

下面咱們來看看關於柔性數組的資料:3d

一、什麼是柔性數組?指針

柔性數組既數組大小待定的數組, C語言中結構體的最後一個元素能夠是大小未知的數組,也就是所謂的0長度,因此咱們能夠用結構體來建立柔性數組。code

二、柔性數組有什麼用途 ?orm

它的主要用途是爲了知足須要變長度的結構體,爲了解決使用數組時內存的冗餘和數組的越界問題。blog

三、用法 :在一個結構體的最後 ,申明一個長度爲空的數組,就可使得這個結構體是可變長的。對於編譯器來講,此時長度爲0的數組並不佔用空間,由於數組名

自己不佔空間,它只是一個偏移量, 數組名這個符號自己代 表了一個不可修改的地址常量 (注意:數組名永遠都不會是指針! ),但對於這個數組的大小,咱們

能夠進行動態分配,對於編譯器而言,數組名僅僅是一個符號,它不會佔用任何空間,它在結構體中,只是表明了一個偏移量,表明一個不可修改的地址常量!

對於柔性數組的這個特色,很容易構造出變成結構體,如緩衝區,數據包等等:

typedef struct _SoftArray

{

    Int len;

    int array[];

}SoftArray;

這樣的變長數組經常使用於網絡通訊中構造不定長數據包,不會浪費空間浪費網絡流量,好比我要發送1024字節的數據,若是用定長包,假設定長包的長度爲2048,就

會浪費1024個字節的空間,也會形成沒必要要的流量浪費。

 

四、舉個簡單是實例

#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的長度,便於肯定循環打印輸出

是循環的次數。

五、運行錯誤的解決

#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」。通常是後者居多。
 
所以,當你碰見這個錯誤的時候,記得去檢查一下本身數組的賦值吧。

六、注意說明

在定義這個結構體的時候,模子的大小就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 }
相關文章
相關標籤/搜索