experchange > c

Thiago Adams (11-08-18, 02:11 AM)
The compiler I frequently use (Visual C++) doesn't
have VLAs, but I can use clang inside VC++ and test the
feature.
I have read a lot about why VLA's are bad etc.. (I agree that
is bat to allocate any size on the stack)

Anyway, today I realized that VLA's are MUCH MORE than
auto allocated arrays on the stack. They add new features
on the C type system and they allow us to write code
in a new way. We can use VLAs on heap.

This sample shows some features, compare this with
your traditional code:

void F(int n, int m, int a[n][m])
{
for (int i = 0; i < n; i++)
{
for (int k = 0; k < m; k++)
{
printf(" %d ", a[i][k]);

}
printf("\n");
}
}

int main()
{
int n = 2;
int m = 3;
int (*p)[n][m] = malloc(sizeof * p); // <- sizeof
int j = 0;

for (int i = 0; i < n; i++)
{
for (int k = 0; k < m; k++)
{
(*p)[i][k] = j; //normal index
j++;
}
}

F(n, m, *p);

free(p);
}

What do you think on these other characteristics of VLA's?
I learned that these types have an especial name 'variably
modified type'.
This syntax is not compatible with C++.

We cannot use this variably types on structs.
As you can see in the sample the syntax is a little
different of normal c code. To use pointer we have to
take the address (pointer to array) instead of just use
pointer with the index.

So, I also was wondering in to use something in structs
specifying a big index or 0 and the use would have **similar syntax**
of pointer to VLA's.

For instance:

struct Item
{
int i;
};

struct Items
{
struct Item * (*Data)[0/*Size*/];
int Size;
};

int main()
{
struct Items items = { 0 };
(*items.Data)[0]->i = 1;
}

Then I read Data as:
Data is a pointer to array of size Size of pointers to Item.

The good point:
You can have the syntax for indexes with more than
one dimension.

Bad point (take the address):
(*items.Data)[0]->i = 1;
the good point of the bad point is that this remind us
that it is a pointer and can be null.

One limitation is that we cannot use this VLAs syntax
on return types. And we always need the variable declared
before the VLA.

Sample:

int (*)[n] Allocate(int n);

or

void Use(int (*)[n], int n);
Ben Bacarisse (11-08-18, 02:58 AM)
Thiago Adams <thiago.adams> writes:

> The compiler I frequently use (Visual C++) doesn't
> have VLAs, but I can use clang inside VC++ and test the
> feature.
> I have read a lot about why VLA's are bad etc.. (I agree that
> is bat to allocate any size on the stack)
> Anyway, today I realized that VLA's are MUCH MORE than
> auto allocated arrays on the stack. They add new features
> on the C type system and they allow us to write code
> in a new way. We can use VLAs on heap.


It's handy to distinguish between variable length arrays and variably
modified types. Your examples are of variably modified types which I
think are an unalloyed good. It's a shame that in C11 (and later) these
two used of the idea are linked so that both are optional.

<snip>
David Brown (11-08-18, 10:40 AM)
On 08/11/18 01:11, Thiago Adams wrote:
> The compiler I frequently use (Visual C++) doesn't
> have VLAs, but I can use clang inside VC++ and test the
> feature.
> I have read a lot about why VLA's are bad etc.. (I agree that
> is bat to allocate any size on the stack)


I use them occasionally.

Sometimes I use them in a way that /is/ compatible with C++ :

static const int max_length = 12;

void foo(void) {
const int buffersize = 2 * max_length + 3;
uint8_t buffer[buffersize];
...
}

Here, "buffer" is a normal array in C++ because C++ has wider
definitions of what is allowed as an integer constant expression. The
compiler knows fine that "buffersize" is always 27, and can use that for
the array size.

In C, the syntax rules and constraints mean that "buffersize" is not an
integer constant expression - so "buffer" is a VLA. But it is a VLA
whose size is known at compile time, the resulting code is identical for
C and C++, and it is equally safe (in terms of not accidentally
allocating more stack than you expect).

I also use "real" VLAs occasionally, for temporary buffers. But I am
very careful to be sure of the maximum size for them - and usually it is
easier to simply use that maximum size as a normal array.

(There is nothing wrong with allocating data on the stack. There is
something very wrong with allocating data without strict controls of the
maximum size, but that is always the case for any allocation.)
Thiago Adams (11-08-18, 01:17 PM)
On Wednesday, November 7, 2018 at 10:58:36 PM UTC-2, Ben Bacarisse wrote:
> Thiago Adams writes:
> It's handy to distinguish between variable length arrays and variably
> modified types. Your examples are of variably modified types which I
> think are an unalloyed good. It's a shame that in C11 (and later) these
> two used of the idea are linked so that both are optional.


Some features like threads makes sense to be optional,
because it depends on the hardware.
But a language feature that doesn't depends on hardware is
very strange to be optional. It is like 'we give up'.

If we look closer, these variably types are not so simpler.
I think the compiler must create additional variables to track
the size of the initialization to be used my sizeof and to
be used by index calculations.

The variably types is not clue with the variable, the variable
can change but the size of the variably type is not changed.

If I had a feature in my source-to-source compiler
to generate equivalent code for variably types I would
add constant variables to keep the size of the initialization.

void F(int n, int m, int a[])
{
const int original_n = n;
const int original_m = m;

for (int i = 0; i < n; i++)
{
for (int k = 0; k < m; k++)
{
printf(" %d ", a[original_m * i + k]);

}
printf("\n");
}
}

int main()
{
int n = 2;
int m = 3;
const int original_n = n;
const int original_m = m;
int(*p)[1] = malloc(sizeof(int) * n * m);

int j = 0;
for (int i = 0; i < n; i++)
{
for (int k = 0; k < m; k++)
{
(*p)[original_m * i + k] = j;
j++;
}
}

F(n, m, *p);

free(p);
}
Ben Bacarisse (11-08-18, 01:51 PM)
Thiago Adams <thiago.adams> writes:

> On Wednesday, November 7, 2018 at 10:58:36 PM UTC-2, Ben Bacarisse wrote:
> Some features like threads makes sense to be optional,
> because it depends on the hardware.
> But a language feature that doesn't depends on hardware is
> very strange to be optional. It is like 'we give up'.


I suspect that is exactly what the committee is saying!

> If we look closer, these variably types are not so simpler.
> I think the compiler must create additional variables to track
> the size of the initialization to be used my sizeof and to
> be used by index calculations.


Yes. I did not mean to suggest that it's trivial, just that there are
two related concepts and both got thrown out when only one of them bore
the brunt of the criticism. Most people object to VLAs because they
fear arbitrary stack allocations no test for success, but variably
modified types can be used to great effect with conventional arrays
(static, local or allocated).

<snip>
Bart (11-08-18, 02:08 PM)
On 08/11/2018 11:51, Ben Bacarisse wrote:
> Thiago Adams <thiago.adams> writes:


> I suspect that is exactly what the committee is saying!
> Yes. I did not mean to suggest that it's trivial,


(I bet David Brown would argue that it is!)

just that there are
> two related concepts and both got thrown out when only one of them bore
> the brunt of the criticism. Most people object to VLAs because they
> fear arbitrary stack allocations no test for success, but variably
> modified types can be used to great effect with conventional arrays
> (static, local or allocated).


What's the difference between a VLA and a local array with a variable
modified type?

How does a variably modified static array work? (I get: "error: storage
size isn't a constant".)

What is a variably modified allocated array; is it just a pointer whose
type happens to be variably modified?

And finally, does a variably modified type have any use other than to
declare some sort of array type? If not, then it's harder to separate
out the feature from a VLA (variable length array).

Unless the difference is that one is the type, the other an actual object.
Thiago Adams (11-08-18, 02:26 PM)
On Thursday, November 8, 2018 at 9:51:33 AM UTC-2, Ben Bacarisse wrote:
....
> Yes. I did not mean to suggest that it's trivial, just that there are
> two related concepts and both got thrown out when only one of them bore
> the brunt of the criticism.


I was trying to say that maybe (I don't know) this could be
one reason for make it optional. No idea.
Thiago Adams (11-08-18, 02:30 PM)
On Thursday, November 8, 2018 at 10:08:50 AM UTC-2, Bart wrote:
> On 08/11/2018 11:51, Ben Bacarisse wrote:
> (I bet David Brown would argue that it is!)
> just that there are
> What's the difference between a VLA and a local array with a variable
> modified type?


variably modified types are arguments or pointers.

> How does a variably modified static array work? (I get: "error: storage
> size isn't a constant".)


You cannot declare it global scope etc.. Search for VLA on the standard.

> What is a variably modified allocated array; is it just a pointer whose
> type happens to be variably modified?
> And finally, does a variably modified type have any use other than to
> declare some sort of array type? If not, then it's harder to separate
> out the feature from a VLA (variable length array).
> Unless the difference is that one is the type, the other an actual object.


See the sample... see sizeof and how it use indexes.
Bart (11-08-18, 02:34 PM)
On 08/11/2018 12:30, Thiago Adams wrote:
> On Thursday, November 8, 2018 at 10:08:50 AM UTC-2, Bart wrote:


>> How does a variably modified static array work? (I get: "error: storage
>> size isn't a constant".)

> You cannot declare it global scope etc.. Search for VLA on the standard.


I tried this:

void fred(int n){
static int a[n];
}

DMC says:

"variable length arrays are only for function prototypes and autos"
Thiago Adams (11-08-18, 02:43 PM)
On Thursday, November 8, 2018 at 10:34:59 AM UTC-2, Bart wrote:
> On 08/11/2018 12:30, Thiago Adams wrote:
> I tried this:
> void fred(int n){
> static int a[n];
> }
> DMC says:
> "variable length arrays are only for function prototypes and autos"


Exactly and it makes sense.
Bart (11-08-18, 02:45 PM)
On 08/11/2018 12:43, Thiago Adams wrote:
> On Thursday, November 8, 2018 at 10:34:59 AM UTC-2, Bart wrote:
> Exactly and it makes sense.


Yes, but I was questioning Ben's remark:

"... but variably modified types can be used to great effect with
conventional arrays (static, local or allocated)."
Thiago Adams (11-08-18, 02:49 PM)
On Thursday, November 8, 2018 at 10:46:12 AM UTC-2, Bart wrote:
> On 08/11/2018 12:43, Thiago Adams wrote:
> Yes, but I was questioning Ben's remark:
> "... but variably modified types can be used to great effect with
> conventional arrays (static, local or allocated)."


"EXAMPLE 4 All declarations of variably modified (VM) types have to be at either block scope or
function prototype scope."
"Finally, all
identifiers declared with a VM type have to be ordinary identifiers and cannot, therefore, be members of
structures or unions."
Search for VM at C standard.
Malcolm McLean (11-08-18, 02:59 PM)
On Thursday, November 8, 2018 at 8:40:40 AM UTC, David Brown wrote:
> (There is nothing wrong with allocating data on the stack. There is
> something very wrong with allocating data without strict controls of the
> maximum size, but that is always the case for any allocation.)

Not on big hosted systems. Stacks should still be kept small for cache
reasons, and because the stack often needs a maximum size which it
obtains on program startup. But you can assume virtually limitless
memory available on the heap, and if it runs out, tell the customer
to buy more memory chips. A gigabyte costs about ten dollars, and a
gigabyte is far more than you need for most applications.
jameskuyper (11-08-18, 03:18 PM)
On Wednesday, November 7, 2018 at 7:11:55 PM UTC-5, Thiago Adams wrote:
....
> I have read a lot about why VLA's are bad etc.. (I agree that


In principle, they present no more of a problem than any other kind of
automatically or statically allocated array - if you declare one that's
too big, you'll run out of memory, and that's equally true whether it's
a VLA or an ordinary array. If you take an automatically allocated
array such as income[MAX_TAXPAYERS], where MAX_TAXPAYERS expands to an
integer constant expression, and replace it with income[taxpayers] where
taxpayers<=MAX_TAXPAYERS, you'll actually end using less space on the
stack.

> is bat to allocate any size on the stack)


I disagree - that depends upon what limits there are on the stack size.
My code normally runs on systems where the stack size can easily be
adjusted (on a per-process basis) to be as large as you need, up to the
upper limits on virtual memory size.

[..]
> different of normal c code. To use pointer we have to
> take the address (pointer to array) instead of just use
> pointer with the index.


Actually, that's not the case. The different syntax is just a side-
effect of how you chose to declare p. If you had chosen to declare p the
same way without using a variably modified type:

int (*p)[3][2] = malloc(sizeof *p);

Then the rest of the program would not have to be changed in any way. On
the other hand, if you'd used the more conventional approach to
declaring a pointer to a two-dimensional array, except that it uses a
variably modified type:

int (*p)[n] = malloc(m * sizeof *p);

Then you could replace (*p)[i][j] with p[i][j].
Scott Lurndal (11-08-18, 04:19 PM)
Malcolm McLean <malcolm.arthur.mclean> writes:
>On Thursday, November 8, 2018 at 8:40:40 AM UTC, David Brown wrote:
>Not on big hosted systems. Stacks should still be kept small for cache
>reasons, and because the stack often needs a maximum size which it
>obtains on program startup.


What operating system allocates max stack at startup? All the systems
I'm familiar with use demand allocation for stack pages; in that respect
they're no different from heap pages - just located in a different
region of the virtual address space.

Cache isn't much of a factor for stack, given the prevalence of
internal 'return stacks' in most modern processor designs.

Similar Threads