變長數(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é)淺,如有疏漏,望指正。