C is unnecessary

Started by
197 comments, last by Enselic 20 years, 1 month ago
quote:Original post by DrPizza
quote:Original post by Mayrel
*Frown* What''s wrong with VLAs?

They introduce complexity yet offer no discernible advantages in return.


The advantages are that you get to allocate an array on the stack even when you don''t know the size of the array until the function it is declared in is called. That''s obviously more efficient than allocating it on the heap.

I don''t see any notable complexity.

int calculate_something_destructive_nondestructively (const char *string) {  char *local_copy[strlen(string)];  strcpy(local_copy, string);  /* Do something */} 


As compared to:

int calculate_something_destructive_nondestructively (const char *string) {  char *local_copy = strdup(string);  /* Do something */  free(local_copy);} 


Now, yes, in C++, you could use std::string or std::auto_ptr to avoid the hassle of having to deallocate the array. But, even then, that is inherently less efficient than using VLAs, because neither class allocates its memory on the stack.
CoV
Advertisement
Why are you still using C?

originally from object mentor
quote:The advantages are that you get to allocate an array on the stack even when you don''t know the size of the array until the function it is declared in is called. That''s obviously more efficient than allocating it on the heap.

If stack allocation is what''s wanted I feel that standardizing alloca() would be cleaner (as a library change I feel should generally be preferred to a language change, if possible).

But VLAs don''t provide alloca(). alloca() -- potentially (if the standard mandated it) -- could provide protection against creating stack-overflowing buffers (it could be mandated to return null if the allocation cannot succeed, so that one could handle the error in a convenient manner or, for example, pick an alternative memory allocation strategy).

It also changes the way sizeof works in a pretty significant way; no longer is sizeof always evaluated at compile-time.

quote:int calculate_something_destructive_nondestructively (const char *string) { char *local_copy[strlen(string)]; strcpy(local_copy, string); /* Do something */}

That code is wrong.

It ought to be { char local_copy[strlen(string) + 1]; }. No * (VLA declarations are written like normal automatic array declarations, and if you wanted to make a pointer to the array, you''d have to write char (*local_copy)[strlen(string) + 1]), and with room for the null.

quote:Now, yes, in C++, you could use std::string or std::auto_ptr to avoid the hassle of having to deallocate the array. But, even then, that is inherently less efficient than using VLAs, because neither class allocates its memory on the stack.

AFAIK nowhere within the C99 standard does it say where the storage used by VLAs is located; VLA storage could in principle be located in some heap-like location with an automatic ''free'' call injected to handle tidy up; that would, I think, fulfil the demands of automatic storage duration.
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;}  /*** drpizza@battleaxe.net ***/
quote:Original post by DrPizza
quote:The advantages are that you get to allocate an array on the stack even when you don''t know the size of the array until the function it is declared in is called. That''s obviously more efficient than allocating it on the heap.

If stack allocation is what''s wanted I feel that standardizing alloca() would be cleaner (as a library change I feel should generally be preferred to a language change, if possible).

I don''t see the issue with a language change that doesn''t invalidate existing code.
quote:
It also changes the way sizeof works in a pretty significant way; no longer is sizeof always evaluated at compile-time.

Is that likely to be a problem? Since the size of a VLA isn''t, by definition, known at compile-time, it''s quite obvious that sizeof won''t complete at compile-time. Are there any situations in which the fact that the size of a VLA isn''t known at compile-time would cause code to break?
quote:
quote:int calculate_something_destructive_nondestructively (const char *string) { char *local_copy[strlen(string)]; strcpy(local_copy, string); /* Do something */}

That code is wrong.

It ought to be { char local_copy[strlen(string) + 1]; }. No * (VLA declarations are written like normal automatic array declarations, and if you wanted to make a pointer to the array, you''d have to write char (*local_copy)[strlen(string) + 1]), and with room for the null.

Quite so. I was foolish enough not to test the code before posting it.
quote:

quote:Now, yes, in C++, you could use std::string or std::auto_ptr to avoid the hassle of having to deallocate the array. But, even then, that is inherently less efficient than using VLAs, because neither class allocates its memory on the stack.

AFAIK nowhere within the C99 standard does it say where the storage used by VLAs is located; VLA storage could in principle be located in some heap-like location with an automatic ''free'' call injected to handle tidy up; that would, I think, fulfil the demands of automatic storage duration.

Well, I don''t think the standard specifies the location for any objects. Certainly, the word "stack" does not appear in the standard at any point.

But, VLAs are defined to have automatic storage duration, and objects with that storage are typically expected to be allocated on the stack.

A possible implementation strategy would be to use alloca() for arrays under a certain size, and malloc() for other arrays.

The key distinction is that whilst it''s always possible that a VLA might not be allocated on the stack, it''s not possible for a function to alloca() memory on the stack frame of the function that called it, including the std::string::string() function.
CoV
quote:Original post by DrPizza
quote:But if C has all of these incredibly valuable features that C++ doesn''t have,

It doesn''t.

C99 introduces some minor features over C++ -- some are good (the various struct initializer features, perhaps restrict), some are bad (VLAs) -- but its expressive power remains significantly inferior to C++''s.


How do you define "power"? If "power" is defined as "multiple ways to do the same thing" then I agree. However, most people would call that "flexibility."


"Unfortunatly, when I sent the email, instead of writing "Best Regards" I ended up writing "Best Retards." - boolean
-~-The Cow of Darkness-~-
I rather think by "expressive power" he means "ability to express algorithms and data in a concise but understandable form."
CoV
Personally, I''d have to say C++ is good for large projects, if your doing something quickly and don''t have time to create some object oreinated stuff then I can see someone tossing together some C code, its less work.
quote:Is that likely to be a problem? Since the size of a VLA isn''t, by definition, known at compile-time, it''s quite obvious that sizeof won''t complete at compile-time. Are there any situations in which the fact that the size of a VLA isn''t known at compile-time would cause code to break?

It''s complexity, that''s all.

quote:A possible implementation strategy would be to use alloca() for arrays under a certain size, and malloc() for other arrays.

That would be a fairly sensible, though I don''t know if any implementations actually do such a thing.

quote:The key distinction is that whilst it''s always possible that a VLA might not be allocated on the stack, it''s not possible for a function to alloca() memory on the stack frame of the function that called it, including the std::string::string() function.

If one wants a fixed-size buffer then std::string rather loses its appeal anyway, so I''m not convinced that that is a significant concern.

char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;}  /*** drpizza@battleaxe.net ***/
Guys, trust me, this is going nowhere.

This topic is closed to new replies.

Advertisement