Re: What's new in C?

On Thursday, November 29, 2012 2:41:15 AM UTC, Cal Dershowitz wrote:
>
> Is there a new standard, like a C 2012, where everyone's happy and
> there's this great moment of aquarius going on in the C community?
>
No.
C99 was a disaster. It was neither sufficiently different from C89
to provide functionality that was widely wanted, nor sufficiently similar
to make it trivial to change a C89 compiler to C99. In addition it had some
bad ideas like variable-length automatic arrays.

The result is that C programmers need to be extremely conservative.
There's no good way of allowing non-Latin characters, for example.

Advertisements

Malcolm McLean wrote:
> On Thursday, November 29, 2012 2:41:15 AM UTC, Cal Dershowitz wrote:
>>
>> Is there a new standard, like a C 2012, where everyone's happy and
>> there's this great moment of aquarius going on in the C community?
>>
> No.
> C99 was a disaster. It was neither sufficiently different from C89
> to provide functionality that was widely wanted, nor sufficiently similar
> to make it trivial to change a C89 compiler to C99. In addition it had some
> bad ideas like variable-length automatic arrays.
>
> The result is that C programmers need to be extremely conservative.
> There's no good way of allowing non-Latin characters, for example.
>

If the featureset of C89 isn't adequate to what you are
trying to do, then - and this is purely IMO - there are
a great many other choices that will probably make more
sense than 'C'.

Variable-length *anything* sounds better than it is, in real life.
As in contracts, get the memory/money up front.

Advertisements

Les Cargill wrote:
> If the featureset of C89 isn't adequate to what you are
> trying to do, then - and this is purely IMO - there are
> a great many other choices that will probably make more
> sense than 'C'.

IMO, you are missing the point. Currently, the C programming language is
the language as described in C11. It doesn't really matter if that language
is a superset of C89 or not, or if the features provided by either revision
are already adequate. The real important aspect is that it is supposed to
be the standard baseline for all which is considered the C programming
language, so that when someone says that program X is written in C, we know
beforehand that we can use feature A, B, or C without wasting time finding
out if any of those features are supported in platform M or N. Once we are
forced to waste time and resources dealing with specific variants of the
same programming language, efficiency certainly won't go up, and things
won't get any simpler or easier than they could be, and should be.

> Variable-length *anything* sounds better than it is, in real life.
> As in contracts, get the memory/money up front.

In practical terms, since C11 VLAs are essentially no longer a part of the C
programming language. So, that's a non-issue.

Nevertheless, VLAs are no worse than using fixed-size arrays. They only
pose a problem if the program was designed poorly.

On Friday, November 30, 2012 10:46:38 AM UTC, Rui Maciel wrote:
> Les Cargill wrote:
>
> Nevertheless, VLAs are no worse than using fixed-size arrays. They only
> pose a problem if the program was designed poorly.
>
With a non-recursive function, stack usage can be calculated at
compile time. Also, f the stack breaks, the sitation is likely to be
detected on the first run.
That's not the case with vlas. They can only be coded safely by imposing
a maximum. But if you set the maximum so that the stack cannot overflow
on any input, normally you must hardcode the maxmium. So there's actually
not much advantage in a vla.

"Malcolm McLean" <> wrote in message
news:...
> On Friday, November 30, 2012 10:46:38 AM UTC, Rui Maciel wrote:
>> Les Cargill wrote:
>>
>> Nevertheless, VLAs are no worse than using fixed-size arrays. They only
>> pose a problem if the program was designed poorly.
>>
> With a non-recursive function, stack usage can be calculated at
> compile time. Also, f the stack breaks, the sitation is likely to be
> detected on the first run.

On my machine, the stack grows dynamically as needed. (I found out when
trying to use a software stack, which didn't have the same property!)

There will be still be an upper physical limit (although it might not be
able to grow as much or as easily as the heap), but a fixed 'stack limit' is
meaningless.

Perhaps on a different platform, but then you wouldn't use VLAs. (Not that
there's anything actually variable about them anyway: as I understand how a
VLA works, once one is created, then they stay the same size! You just don't
know the size until runtime.)

Malcolm McLean wrote:
> With a non-recursive function, stack usage can be calculated at
> compile time. Also, f the stack breaks, the sitation is likely to be
> detected on the first run.
> That's not the case with vlas. They can only be coded safely by imposing
> a maximum. But if you set the maximum so that the stack cannot overflow
> on any input, normally you must hardcode the maxmium. So there's actually
> not much advantage in a vla.

That's exactly why VLAs, when used properly, can be an improvement over
fixed-length arrays (FLAs).

VLAs tend to be depicted as a way to get arrays larger than the one needed
by FLAs, but it's actually the other way around. With VLAs, it's possible
to calll functions which declare arrays that are smaller than what would
otherwise be required by a FLA solution. Therefore, if VLAs are allocated
in the stack, the worst case scenario is that they require as much stack
space as the FLA solution, and in any other case they will take over less
memory than what would otherwise be allocated. This is an improvement, and
can be a significant one, as it reduces the chances of overflowing the call
stack. This might look like nit picking, but high availability is achieved
through nit picking.

So, along with the syntactic sugar side of VLAs, using them does have its
advantages, and depending on the application and how they are used, they
might actually be significant.

Rui Maciel <> wrote:
> Malcolm McLean wrote:
>> With a non-recursive function, stack usage can be calculated at
>> compile time. Also, f the stack breaks, the sitation is likely to be
>> detected on the first run.

In the days of fixed sized small stacks, I suppose that is true.
Maybe it still is for embedded systems. I remember dynamic stacks
back to OS/2 1.2, though. The linker required one to set a stack
size if larger than the default 4K, but I could make it really big
(more than available virtual memory) and it worked fine.
>> That's not the case with vlas. They can only be coded safely by imposing
>> a maximum. But if you set the maximum so that the stack cannot overflow
>> on any input, normally you must hardcode the maxmium. So there's actually
>> not much advantage in a vla.

Is it required that VLAs be stack allocated?

Stack allocation of large arrays has been a Fortran problem for
a long time. There are assumptions, mostly from C, that automatic
arrays should be small, which isn't always true. Also, Fortran can
sometimes allocate temporary arrays of unknown (at compile time) size.
> That's exactly why VLAs, when used properly, can be an improvement over
> fixed-length arrays (FLAs).

That seems useful to me. Even more, in the case of recursion, you
can size each instance as appropriate.
> VLAs tend to be depicted as a way to get arrays larger than the one needed
> by FLAs, but it's actually the other way around. With VLAs, it's possible
> to calll functions which declare arrays that are smaller than what would
> otherwise be required by a FLA solution. Therefore, if VLAs are allocated
> in the stack, the worst case scenario is that they require as much stack
> space as the FLA solution, and in any other case they will take over less
> memory than what would otherwise be allocated. This is an improvement, and
> can be a significant one, as it reduces the chances of overflowing the call
> stack. This might look like nit picking, but high availability is achieved
> through nit picking.

Well, in the case of recursion, you can never be sure how big the
stack needs to be, in cases where recursion depth (and array size)
depends on input data. But also, most systems allow changing the
stack size without recompiling.
> So, along with the syntactic sugar side of VLAs, using them does have its
> advantages, and depending on the application and how they are used, they
> might actually be significant.

Note that PL/I has had variable length AUTO arrays since day zero.
(Sometime in the mid 1960's.)

(Well, OS/360 doesn't have a stack, so everything was heap allocated.
To speed thing up, it would allocate a large (maybe 4K) block and then
divide that up among the different DSAs.)

In the days of small computers, it may have made sense to allocate small
local arrays (of fixed size) on the stack, and large ones on the heap.
Other languages never had the same distinction.

On 11/30/2012 11:41 AM, glen herrmannsfeldt wrote:
....
>> Malcolm McLean wrote:
>>> That's not the case with vlas. They can only be coded safely by imposing
>>> a maximum. But if you set the maximum so that the stack cannot overflow
>>> on any input, normally you must hardcode the maxmium. So there's actually
>>> not much advantage in a vla.
>
> Is it required that VLAs be stack allocated?

No. As far as the C standard is concerned, nothing is required to be
stack allocated.

On Friday, November 30, 2012 4:41:05 PM UTC, glen herrmannsfeldt wrote:
> Rui Maciel <> wrote:
>
> In the days of small computers, it may have made sense to allocate small
> local arrays (of fixed size) on the stack, and large ones on the heap.
>
> Other languages never had the same distinction.
>
Also it makes it easier to design hardware, if yiu know that the stack
will be relatively small.

A high-level language usually creates most objects on the heap, transparently
to the user. That's reasonable for a high-level language.

VLAs (at least named objects defined as VLAs) have automatic storage
duration, so their lifetimes end at the end of the enclosing block.
That's stack-like in the sense of first-in last-out allocation
and deallocation. How that's achieved is up to the compiler.

Having said that, I'd be surprised if there were any compiler
that didn't allocate VLAs on a contiguous stack. There have
been compilers, particularly on some IBM mainframes, that don't
use a contiguous stack for local variables; I suspect they don't
support VLAs.

Note that objects of VLA type *can* be allocated via malloc().

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Rui Maciel <> writes:
[...]
> IMO, you are missing the point. Currently, the C programming language
> is the language as described in C11. It doesn't really matter if that
> language is a superset of C89 or not, or if the features provided by
> either revision are already adequate. The real important aspect is
> that it is supposed to be the standard baseline for all which is
> considered the C programming language, so that when someone says that
> program X is written in C, we know beforehand that we can use feature
> A, B, or C without wasting time finding out if any of those features
> are supported in platform M or N. Once we are forced to waste time
> and resources dealing with specific variants of the same programming
> language, efficiency certainly won't go up, and things won't get any
> simpler or easier than they could be, and should be.

That's certainly the *purpose* of the C standard. Unfortunately, it
hasn't been achieved.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

No. One plausible approach would be to malloc() space
for the array and insert a compiler-generated free() at block
exit. This could be trickier than might appear at first glance,
though, since the block might exit via longjmp().

Another possibility is to defer deallocation until some
convenient later time, like the next time a VLA is created.
VLA memory could be obtained from malloc() and appended to a
LIFO linked list of such areas, tagged with the "stack depth"
of the requestor. At the next VLA allocation, the new requestor's
depth is determined and any areas allocated at deeper levels are
discarded. (A semi-portable alloca() replacement by DA Gwyn
works this way.) This could be combined with the first approach
to provide a safety net for the longjmp() case.

Keith Thompson <> wrote:
> glen herrmannsfeldt <> writes:
> [...]
>> Is it required that VLAs be stack allocated?
> [...]
> VLAs (at least named objects defined as VLAs) have automatic storage
> duration, so their lifetimes end at the end of the enclosing block.
> That's stack-like in the sense of first-in last-out allocation
> and deallocation. How that's achieved is up to the compiler.
> Having said that, I'd be surprised if there were any compiler
> that didn't allocate VLAs on a contiguous stack. There have
> been compilers, particularly on some IBM mainframes, that don't
> use a contiguous stack for local variables; I suspect they don't
> support VLAs.

As far as I know, there was never a C compiler for OS/360, but
I know in some detail how the OS/360 PL/I compiler does its
allocation, including automatic arrays. As there is no stack,
they have to be allocated on procedure entry and deallocated
on exit. (And PL/I allows for a GOTO out of a procedure, not
so different from C's longjmp().) Because of the overhead of
GETMAIN (the OS/360 and successor allocation call) it is usual
to allocate a somewhat larger block and parcel it out as needed.

It doesn't seem much harder to allocate a variable sized block
on entry than a fixed sized block. Fragmentation of free memory
is always a problem, though.

I suppose fixed size is convenient for instruction sets that
can index off a stack pointer or frame pointer. VLAs will require
a more complicated origin calculation.
> Note that objects of VLA type *can* be allocated via malloc().

Seems that the compiler could call malloc() for you at entry
and free() before return. Maybe only in the case of especially
large arrays.

"glen herrmannsfeldt" <> wrote in message
news:k9bbr0$6qo$...
> Keith Thompson <> wrote:
>> VLAs (at least named objects defined as VLAs) have automatic storage
>> duration, so their lifetimes end at the end of the enclosing block.
>> That's stack-like in the sense of first-in last-out allocation
>> and deallocation. How that's achieved is up to the compiler.
> I suppose fixed size is convenient for instruction sets that
> can index off a stack pointer or frame pointer. VLAs will require
> a more complicated origin calculation.

If there's only one VLA, it can go at the end following the other fixed
objects.

Otherwise, VLAs can just be implemented via a pointer (pointing further down
the stack). Then all the local named objects will be at fixed offsets. The
variable-sized section of stack can follow.

(snip regarding VLAs)
>> I suppose fixed size is convenient for instruction sets that
>> can index off a stack pointer or frame pointer. VLAs will require
>> a more complicated origin calculation.
> If there's only one VLA, it can go at the end following the other fixed
> objects.

Yes, I thought about that but didn't say it.
> Otherwise, VLAs can just be implemented via a pointer (pointing further down
> the stack). Then all the local named objects will be at fixed offsets. The
> variable-sized section of stack can follow.

Yes. So, on many processors, one more instruction for each access.
A small cost for the convenience.

Cal Dershowitz <> writes:
> On 11/30/2012 12:12 PM, Keith Thompson wrote:
>> glen herrmannsfeldt <> writes:
>> [...]
>>> Is it required that VLAs be stack allocated?
>> [...]
>>
>> VLAs (at least named objects defined as VLAs) have automatic storage
>> duration, so their lifetimes end at the end of the enclosing block.
>> That's stack-like in the sense of first-in last-out allocation
>> and deallocation. How that's achieved is up to the compiler.
>>
>> Having said that, I'd be surprised if there were any compiler
>> that didn't allocate VLAs on a contiguous stack. There have
>> been compilers, particularly on some IBM mainframes, that don't
>> use a contiguous stack for local variables; I suspect they don't
>> support VLAs.
>>
>> Note that objects of VLA type *can* be allocated via malloc().
>
> Anyone have any source?

Can you be more specific?

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Cal Dershowitz <> writes:
> On 12/04/2012 01:43 AM, Keith Thompson wrote:
>> Cal Dershowitz <> writes:
>>> On 11/30/2012 12:12 PM, Keith Thompson wrote:
>>>> glen herrmannsfeldt <> writes:
>>>> [...]
>>>>> Is it required that VLAs be stack allocated?
>>>> [...]
>>>>
>>>> VLAs (at least named objects defined as VLAs) have automatic storage
>>>> duration, so their lifetimes end at the end of the enclosing block.
>>>> That's stack-like in the sense of first-in last-out allocation
>>>> and deallocation. How that's achieved is up to the compiler.
>>>>
>>>> Having said that, I'd be surprised if there were any compiler
>>>> that didn't allocate VLAs on a contiguous stack. There have
>>>> been compilers, particularly on some IBM mainframes, that don't
>>>> use a contiguous stack for local variables; I suspect they don't
>>>> support VLAs.
>>>>
>>>> Note that objects of VLA type *can* be allocated via malloc().
>>>
>>> Anyone have any source?
>>
>> Can you be more specific?
>
> sure. I can think of fortran, where one has allocatable. I can think
> of perl, where it happens automagically.
>
> I've read more of chuck's realloc posts than I can shake a stick at.
>
> What functionality would vla's provide over k&r2 C?

There are two things involved in what goes by the shorthand of VLA: the
objects themselves and their types. What most people call "a VLA" is a
variable length array created using a declaration involving what is
called a variably modified type, like this:

void f(unsigned sz)
{
int data[sz];
...
}

This is not possible K&R2 C (which is basically ANSI C, or C90).

The discussion you commented on was about whether 'data' must be
allocated on "the stack" and the answer is no -- all that's required by
the language is that 'data' be created when the declaration is
encountered (executed if you like) and that it is destroyed when f
returns. In fact, even that's not required. The program must behave as
if that's what's happening, but a clever compiler might be able to do
something else.

The key to understanding Keith Thompson's remark: "Note that objects of
VLA type *can* be allocated via malloc()" is understanding the type not
the object. In C99 you can write

(I've used a 2D array because the technique comes into its own when
there is more than one dimension to the array.) You can argue, if you
like, that there's no VLA here at all -- all there is is an pointer
object whose type is a pointer to a variably modified type (also called
a variable array type). At any rate, there is certainly no automatic
allocation of an array object. What you gain from being able to use a
run-time size is simplicity in indexing. In "old" C, you'd have to
calculate the offset using a multiplication yourself.

The other great boon of these types is when writing functions. In C99
you can write:

void f(unsigned n, unsigned m, int matrix[n][m])
{
...
}

and you can then access the elements of 'matrix' using plain array
indexing notation (matrix[j] for example). The first size, n, is not
really important because arrays are passed as pointers: you could just
as well have written either of

The latest standard, C11, has made VLA's optional. I think this is a
shame, but I think it is particularly a shame that the *types* have been
made optional, because they are useful way beyond the automatic
allocation of variable length arrays. If it was the existence of
environments in which such an allocation is not convenient, then only
the array declarations should have been removed from C11.

On 12/4/2012 3:53 AM, Cal Dershowitz wrote:
> On 11/30/2012 01:52 PM, Eric Sosman wrote:
>> On 11/30/2012 11:41 AM, glen herrmannsfeldt wrote:
>>>
>>> Is it required that VLAs be stack allocated?
>>
>> No. One plausible approach would be to malloc() space
>> for the array and insert a compiler-generated free() at block
>> exit. This could be trickier than might appear at first glance,
>> though, since the block might exit via longjmp().
>>
>> Another possibility is to defer deallocation until some
>> convenient later time, like the next time a VLA is created.
>> VLA memory could be obtained from malloc() and appended to a
>> LIFO linked list of such areas, tagged with the "stack depth"
>> of the requestor. At the next VLA allocation, the new requestor's
>> depth is determined and any areas allocated at deeper levels are
>> discarded. (A semi-portable alloca() replacement by DA Gwyn
>> works this way.) This could be combined with the first approach
>> to provide a safety net for the longjmp() case.
>>
>
> sounds like a library issue.

Not entirely: The library and compiler must cooperate.

For the first approach described, the compiler needs to
generate the malloc() and free() calls, and needs to ensure
that the latter are executed no matter how the block exits.
Getting the free() to execute in the face of a longjmp() that
leaps back to a remote caller requires a certain intimacy
between compiler and library.

The second approach relies on determining the call depth,
which the library cannot do without knowing something about
how the compiler generates code. DA Gwyn's alloca() simply
assumes that the compiler puts `auto' variables on a stack
that grows either up or down uniformly (that is, deeper frames
always use higher addresses or always use lower addresses).
This would not work at all with a compiler using a linked list
of stack frames scattered throughout memory. The library cannot
do the whole job unaided; at the very least it needs assurances
from the compiler.

On Tuesday, December 4, 2012 12:50:43 PM UTC, Ben Bacarisse wrote:
> Cal Dershowitz <> writes:
>
> The latest standard, C11, has made VLA's optional. I think this is a
> shame, but I think it is particularly a shame that the *types* have been
> made optional, because they are useful way beyond the automatic
> allocation of variable length arrays.
>
Yes, it doesn't usually make sense to hardcode the dimensions of 2D
arays at compile time. However the exceptions (4x4 matrices for 3D
graphics, chess boards, 3x3 pixel regions for binary images, screens
on low end graphics hardware) aren't so uncommon that you don't have a
syntax that is in use.
Calculating offsets is silly.

(snip)
>> sure. I can think of fortran, where one has allocatable.
>> I can think of perl, where it happens automagically.
>> I've read more of chuck's realloc posts than I can shake a stick at.
>> What functionality would vla's provide over k&r2 C?
> There are two things involved in what goes by the shorthand of VLA: the
> objects themselves and their types. What most people call "a VLA" is a
> variable length array created using a declaration involving what is
> called a variably modified type, like this:
> void f(unsigned sz)
> {
> int data[sz];
> ...
> }
> This is not possible K&R2 C (which is basically ANSI C, or C90).

Well, in C90 you just say:

int *data=malloc(sz*sizeof(*data));

(and don't forget to free() it later.)

One advantage is that it is much easier to read in VLA form,
the other is the compiler has to remember to free it, not you.
(Even if you put a return in the middle of the function.)
> The discussion you commented on was about whether 'data' must be
> allocated on "the stack" and the answer is no -- all that's required by
> the language is that 'data' be created when the declaration is
> encountered (executed if you like) and that it is destroyed when f
> returns. In fact, even that's not required. The program must behave as
> if that's what's happening, but a clever compiler might be able to do
> something else.

Isn't it allocated on function entry? So, any values needed for the
dimensions must be known at entry.

(PL/I has BEGIN blocks such that you can allocate inside a procedure,
but C doesn't have those.)

(snip on malloc() allocation of VLAs.)
> The other great boon of these types is when writing functions. In C99
> you can write:
> void f(unsigned n, unsigned m, int matrix[n][m])
> {
> ...
> }
> and you can then access the elements of 'matrix' using plain array
> indexing notation (matrix[j] for example). The first size, n, is not
> really important because arrays are passed as pointers: you could just
> as well have written either of

This has been in Fortran since Fortran 66. There was no dynamic
allocation in Fortran until Fortran 90, but variable dimensions like
this were allowed for subroutine and function arguments.
> void f(unsigned n, unsigned m, int matrix[][m])
> void f(unsigned n, unsigned m, int (*matrix)[m])

In Fortran 66, it was common to use 1 for the rightmost
subscript (Fortran is column major) assuming no bounds
checking. Fortran 77 added the * for assumed size.

It was usual, then, to pass to a called routine both the
allocated size and the actual size. One might, for example,
declare a 10 by 10 matrix, but only store the data for
a 5 by 5 matrix.
> but the second size, m, is a great help.

It is. Well, reasonably common in C was instead to allocate
an array of pointers and pass that. Then the called routine
could index through the pointer array. It isn't so obvious
which is faster on either traditional or current processors.

All these happen natually if a pointer to the array is passed.
> The latest standard, C11, has made VLA's optional. I think this is a
> shame, but I think it is particularly a shame that the *types* have been
> made optional, because they are useful way beyond the automatic
> allocation of variable length arrays. If it was the existence of
> environments in which such an allocation is not convenient, then only
> the array declarations should have been removed from C11.

So, compilers can claim to follow both C11 and C01, such that
users know they have features from both standards.

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!