繁体   English   中英

C 语言的可变修改类型

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

ab都是可变长度 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()内部,名称ab基本上是指向可变修改类型的指针。

否则,您可以像对固定大小的数组一样执行此操作:

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。

强制神马: https://godbolt.org/z/zGe4K5hez

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM