C語言中長度為0的數組詳解

概述

長度為0的數組在標準c和c++中是不合法的,但是在gcc中是可行的。

長度為0數組它的最典型的用法就是位於結構體中的最後一項。

使用方式

如下面的例子,分別使用長度為0的數組和指針聲明結構體,實現可變長度的數組功能:

#include <stdio.h>
#include <stdlib.h>
struct test1
{
    int a;
    int b[0];
};
struct test2
{
    int a;
    int *b;
};
struct test3
{
    int a;
    int reserved;//占位符,64位系統中保證結構體字節對齊,test2中是由編譯器對齊的,所以兩個結構體占用空間相同
    int *b;
};
int main()
{
    struct test1 *var1;
    struct test2 *var2;
    int iLength = 10;
    int i;
    printf("the length of struct test1:%d\n",sizeof(struct test1));
    printf("the length of struct test2:%d\n",sizeof(struct test2));
    printf("the length of struct test3:%d\n",sizeof(struct test3));
    var1=(struct test1*)malloc(sizeof(struct test1) + sizeof(int) * iLength);
    var1->a=iLength;
    for(i=0; i < var1->a; i++)
    {
        var1->b[i]=i;
        printf("var1->b[%d]=%d\t", i, var1->b[i]);
    }
    printf("\n"); 
    printf("p var1 = %p\n", var1);
    printf("p var1->a %p\n", &var1->a);
    printf("var1->b %p\n", var1->b);
    printf("p var1->b %p\n", &var1->b);
    printf("p var1->b[0] %p\n", &var1->b[0]);
    printf("p var1->b[1] %p\n", &var1->b[1]);
    printf("\n\n");
    var2=(struct test2*)malloc(sizeof(struct test2));
    var2->a=iLength;
    var2->b=(int *)malloc(sizeof(int) * iLength);
    for(i=0; i < var2->a; i++)
    {
        var2->b[i]=i;
        printf("var2->b[%d]=%d\t", i, var2->b[i]);
    }
    printf("\n"); 
    printf("p var2 = %p\n", var2);
    printf("p var2->a %p\n", &var2->a);
    printf("var2->b %p\n", var2->b);
    printf("p var2->b %p\n", &var2->b);
    printf("p var2->b[0] %p\n", &var2->b[0]);
    printf("p var2->b[1] %p\n", &var2->b[1]);
    free(var1);
    free(var2->b);
    free(var2);
    return 0;
}

64位linux系統中運行結果

the length of struct test1:4
the length of struct test2:16
the length of struct test3:16
var1->b[0]=0    var1->b[1]=1    var1->b[2]=2    var1->b[3]=3    var1->b[4]=4    var1->b[5]=5    var1->b[6]=6    var1->b[7]=7    var1->b[8]=8    var1->b[9]=9
p var1 = 0x55eb1a7d7670
p var1->a 0x55eb1a7d7670
var1->b 0x55eb1a7d7674
p var1->b 0x55eb1a7d7674
p var1->b[0] 0x55eb1a7d7674
p var1->b[1] 0x55eb1a7d7678
var2->b[0]=0    var2->b[1]=1    var2->b[2]=2    var2->b[3]=3    var2->b[4]=4    var2->b[5]=5    var2->b[6]=6    var2->b[7]=7    var2->b[8]=8    var2->b[9]=9
p var2 = 0x55eb1a7d76b0
p var2->a 0x55eb1a7d76b0
var2->b 0x55eb1a7d76d0
p var2->b 0x55eb1a7d76b8
p var2->b[0] 0x55eb1a7d76d0
p var2->b[1] 0x55eb1a7d76d4

使用長度為0的數組可以比指針更方便地進行內存的管理。

結構體test1在分配內存時,則是采用一次分配的原則,一次性將所需的內存全部分配給它,釋放也是一次釋放。數組和結構體的內存是連續的。

結構體test2在分配內存時,需采用兩步:首先,需為結構體分配一塊內存空間;其次再為結構體中的成員變量分配內存空間。這樣兩次分配的內存是不連續的,需要分別對其進行管理。當使用長度為0的數組時,則是采用一次分配的原則,一次性將所需的內存全部分配給它。相反,釋放時也是一樣的。

總結

長度為0的數組並不占有內存空間,而指針方式需要占用內存空間。

對於長度為0的數組,在申請內存空間時,采用一次性分配的原則進行;對於包含指針的結構體,才申請空間時需分別進行,釋放時也需分別釋放。

對於長度為0的數組元素的訪問可正常采用數組方式進行。

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: