Can anyone explain what a variably modified type is?
If we have an array
a[n]
andn
is not known at compile time thena
is a VLA. Given an arrayb[c][d]
wherec
andd
are not known until runtime impliesb
is a VLA, right?
In my book they have said that a variably modified type contains a VLA. That's it; nothing more.
How do I create a pointer to a variably modified type?
A variably-modified type is a VLA (variable length array). There's a similar type in a structure with a flexible array member, but I don't plan to discuss flexible array members further.
The key point about a VLA is that the dimension of an array is not known until run-time. Classically, in C89 and before the standard, all dimensions of an array except the first had to be a known constant value at compile time (and the first dimension could be specified as int a[]
or int b[][SIZE]
or int c[][SIZE1][SIZE2]
where the sizes are constants).
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])
{
...
}
Both a
and b
are variable length arrays. Prior to C99, you could not have written some_function()
like that; the size of the arrays would have to be known at compile time as compile-time constants. Similarly, the notation for another_function()
would not have been legal before C99.
You could, and still can (for reasons of backwards compatibility, if nothing else) write a moderate simulation of another_function()
:
enum { FIXED_SIZE = 32 };
void yet_another_function(int a[], int n, int b[][FIXED_SIZE], int c)
{
...
}
This isn't a perfect simulation because the FIXED_SIZE is a fixed size, but the pure C99 VLA code has a variable dimension there. Old code would often, therefore, use a FIXED_SIZE that was large enough for the worst case.
Inside another_function()
, the names a
and b
are basically pointers to variably modified types.
Otherwise, you do it the same as for a fixed size array:
int z[FIXED_SIZE];
int (*z_pointer)[FIXED_SIZE] = &z;
int v[n];
int (*v_pointer)[n] = &v;
VLA == Variable Length Array
Variable Length Arrays were introduced in the C99 spec to allow for things like this:
int someArraySize;
int myArray[someArraySize];
Variably Modified type is the type of a Variable Length Array. Thus, a Variably Modified type CONTAINS a VLA. In the case of your example of b[c][d] where c and d are not known until run time, b is a Variably Modified type that happens to be a Variable Length multi-dimensional array. b[c][d] is a variable length array of variable length arrays-- phew, what a mouthful.
Here is a great source I found that describes these VLAs and the Variably Modified type with examples:
http://gustedt.wordpress.com/2011/01/09/dont-be-afraid-of-variably-modified-types/
VMT is a type usually used to allocate heap blocks of VMT size. The pointer to VMT is not 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;
}
Some people prefer to call them "VLA on the heap". For some people that defeats the purpose of VLAs. For them, VLA is a small(er) array on the stack.
{ // VMT is a type of VLA
VMT VLA ;
VLA[0] = argv[0] ;
}
No mem leak here. But then some people are wondering what the fuss is all about.
{
typedef char * VMT [argc] ;
VMT * vmt_ptr = alloca(sizeof(VMT));
* vmt_ptr[0] = argv[0] ;
}
They are using alloca, using the VMTs in the process. Effectively creating VMT pointers to blocks allocated on stack space.
There are valid use cases for all three snippets. I hope also showing what are the VMT's.
Mandatory Godbolt: https://godbolt.org/z/zGe4K5hez
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.