C柔性數(shù)組和變長數(shù)組

變長數(shù)組

C語言在C99以前,數(shù)組的維度必須是整數(shù)常量表達(dá)式, 而C99則做了很大改進(jìn),允許數(shù)組維度為整形變量或者整形表達(dá)式(關(guān)鍵點運(yùn)行時才能確定)。這種數(shù)組稱為(variable-length array),簡稱VLA,中文一般稱為變長數(shù)組。
例如:

int n;
scanf("%d", &n);
int array[n];

以上這種寫法在C99 以前是不會通過編譯的。那么VLA是怎么實現(xiàn)的呢?
看看下面的柔性數(shù)組或許有些啟發(fā)。

柔性數(shù)組

例如要在結(jié)構(gòu)體中存放一個長度不固定的字符串,可以采用下面這種方式。

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

typedef struct line
{
    int len;
    char *contents;
}line;

int main(int argc, char **argv)
{
    char str[] = "hello world";

    struct line *ptr = (struct line*)malloc(sizeof(line) + strlen(str) + 1);
    
    ptr->len = strlen(str);
    strcpy((char*)(ptr + 1), str);
     /*
    printf("start: %p\n\n", (char*)ptr);

    printf("(char*)(ptr+1)address: %p\n", (char*)(ptr+1));
    printf("(char*)(ptr+1): %s\n\n", (char*)(ptr+1));

    printf("&(ptr->contents): %p\n", &(ptr->contents));
    printf("ptr->contents: %s\n\n", ptr->contents);

    printf("sizeof(int): %d\n", sizeof(int));
    printf("sizeof(line): %d\n", sizeof(line));
    */
}
/*
 *注釋掉的代碼用于查看內(nèi)存地址,方便理解,順便可以發(fā)現(xiàn)內(nèi)存對齊現(xiàn)象。
 *編譯: Linux gcc.
 */

但這樣處理等同于浪費(fèi)掉了*contents, 且取用字符串時, 必須用(char*)(ptr+1)的方式, 那么有沒有可以既可以不浪費(fèi)掉*contents, 又可以直接用ptr->contents的方式取字符串呢?那么就要靠下面展示的柔性數(shù)組(零長數(shù)組)了。

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

typedef struct line
{
    int len;
    char contents[0];    // 修改的地方。
}line;

int main(int argc, char **argv)
{
    char str[] = "hello world";

    struct line *ptr = (struct line*)malloc(sizeof(line) + strlen(str) + 1);
    
    ptr->len = strlen(str);
    strcpy((char*)(ptr + 1), str);
  /*
    printf("start: %p\n\n", (char*)ptr);

    printf("(char*)(ptr+1)address: %p\n", (char*)(ptr+1));
    printf("(char*)(ptr+1): %s\n\n", (char*)(ptr+1));

    printf("&(ptr->contents): %p\n", &(ptr->contents));
    printf("ptr->contents: %s\n\n", ptr->contents);


    printf("sizeof(int): %d\n", sizeof(int));
    printf("sizeof(line): %d\n", sizeof(line));
  */
}

這樣做的巧妙之處,數(shù)組長度為0的contents并不會占用內(nèi)存空間,這個非對象符號僅僅代表一個地址而已。但C語言標(biāo)準(zhǔn)庫不允許定義長度為0的數(shù)組,能否實現(xiàn)要靠編譯器是否有擴(kuò)展該功能。
所以按照柔性數(shù)組我們可以猜測一下VLA大概實現(xiàn)(僅僅是猜測, 我也不知道對不對):

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

typedef struct Array{
    int data[0];
}Array;

int main(int argc, char **argv)
{
    int n;
    scanf("%d", &n);
    Array *p = (Array*)malloc(sizeof(int) * n);
        
    ((int*)p)[0] = 10;
    ((int*)p)[1] = 20;
    ((int*)p)[2] = 30;

    printf("n=%d, %d, %d, %d\n", n, ((int*)p)[0], ((int*)p)[1], ((int*)p)[2]);
}

好吧,VLA和柔性數(shù)組大概就介紹這么多,才疏學(xué)淺,如有疏漏,望指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容