[英]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.