[英]Variably modified type in C language
誰能解釋什么是可變修改類型?
在我的書中,他們說可變修改類型包含 VLA。 而已; 而已。
如何創建指向可變修改類型的指針?
可變修改類型是 VLA(可變長度數組)。 在具有靈活數組成員的結構中有一個類似的類型,但我不打算進一步討論靈活數組成員。
VLA 的關鍵點是數組的維數直到運行時才知道。 傳統上,在 C89 和標准之前,數組的所有維度除了第一個維度在編譯時必須是已知常量值(並且第一個維度可以指定為int a[]
或int b[][SIZE]
或int c[][SIZE1][SIZE2]
其中大小是常量)。
void some_function(int n)
{
int a[n];
int c = n+1;
int d = n+2;
int b[c][d];
another_function(n, a, c, d, b);
...
}
void another_function(int n, int a[n], int c, int d, int b[c][d])
{
...
}
a
和b
都是可變長度 arrays。在 C99 之前,你不能這樣寫some_function()
; arrays 的大小必須在編譯時作為編譯時常量已知。 同樣, another_function()
的表示法在 C99 之前是不合法的。
您可以並且仍然可以(出於向后兼容性的原因,如果沒有別的原因)編寫another_function()
的適度模擬:
enum { FIXED_SIZE = 32 };
void yet_another_function(int a[], int n, int b[][FIXED_SIZE], int c)
{
...
}
這不是一個完美的模擬,因為 FIXED_SIZE 是固定大小,但純 C99 VLA 代碼在那里有一個可變維度。 因此,舊代碼通常會使用足夠大的 FIXED_SIZE 來應對最壞的情況。
在another_function()
內部,名稱a
和b
基本上是指向可變修改類型的指針。
否則,您可以像對固定大小的數組一樣執行此操作:
int z[FIXED_SIZE];
int (*z_pointer)[FIXED_SIZE] = &z;
int v[n];
int (*v_pointer)[n] = &v;
VLA == 可變長度數組
在 C99 規范中引入了可變長度 Arrays 以允許這樣的事情:
int someArraySize;
int myArray[someArraySize];
可變修改類型是可變長度數組的類型。 因此,可變修改類型包含一個 VLA。 對於您的 b[c][d] 示例,其中 c 和 d 在運行時之前是未知的,b 是可變修改類型,恰好是可變長度多維數組。 b[c][d] 是一個由可變長度數組組成的可變長度數組——哎呀,多啰嗦。
這是我發現的一個很好的來源,它通過示例描述了這些 VLA 和 Variably Modified 類型:
http://gustedt.wordpress.com/2011/01/09/dont-be-afraid-of-variably-modified-types/
VMT 是一種通常用於分配 VMT 大小的堆塊的類型。 指向 VMT 的指針不是 VLA。
#include <stdlib.h>
int main( const int argc, char * const argv[argc])
{
typedef char * VMT [argc] ;
VMT * vmt_ptr = malloc(sizeof(VMT));
* vmt_ptr[0] = argv[0] ;
free(vmt_ptr);
return 42;
}
有些人更喜歡稱它們為“堆上的 VLA”。 對於某些人來說,這違背了 VLA 的目的。 對於他們來說,VLA 是堆棧上的一個小(呃)數組。
{ // VMT is a type of VLA
VMT VLA ;
VLA[0] = argv[0] ;
}
這里沒有內存泄漏。 但后來有些人想知道大驚小怪是怎么回事。
{
typedef char * VMT [argc] ;
VMT * vmt_ptr = alloca(sizeof(VMT));
* vmt_ptr[0] = argv[0] ;
}
他們正在使用 alloca,在此過程中使用 VMT。 有效地創建指向分配在堆棧空間上的塊的 VMT 指針。
所有三個片段都有有效的用例。 我還希望展示什么是 VMT。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.