Re: OT: Language War (Re: "C" Manual)
On Sun, Jan 06, 2002 at 04:48:24PM -0800, Eric G. Miller wrote:
| On Sun, 6 Jan 2002 16:48:31 -0500 (EST), William T Wilson <fluffy@snurgle.org> wrote:
|
| > On Sat, 5 Jan 2002, Eric G.Miller wrote:
| >
| > > is one of the reasons pointers to char are so common. However, there
| > > is a little trick that's guaranteed to always work:
| > >
| > > struct foo {
| > > size_t length;
| > > char str[1];
| > > };
| > >
| > > ...
| > >
| > > struct foo * str_to_foo(char *a)
| > > {
| > > size_t len = strlen (a);
| > > struct foo *bar = malloc (sizeof(struct foo) + len);
| > > if (bar) {
| > > bar->length = len;
| > > memcpy (bar->str, a, len); /* bar->str now not NUL terminated */
| > > }
| > > return bar;
| > > }
| >
| > It doesn't look particularly guaranteed to me.
|
| > You're really allocating *three* pieces of memory here - one for
| > the struct foo, one for the 1-character array chr, and one for the
| > rest of the string.
One piece -- there is only 1 malloc() call.
| > Your example assumes that chr will be located in memory
| > immediately after foo - which it probably will, but it might not.
| > It could be anywhere, the language makes no guarantee. The
| > compiler might even choose to put the 1-char array before foo, so
| > you can't use it without overwriting your struct
Good thought, but I think Eric is right here
| It *is* one chunk of memory, and it does work. The compiler is not allowed
| to reorder the members of the struct. A pointer to the struct is always
| guaranteed to be a pointer to the first element, as well.
GTK+ achieves inheritance by (ab)using this feature. Example :
struct Base
{
int member1 ;
}
struct Child
{
struct Base b ;
int member2 ;
}
you can then case a Child* to a Base* and it will work. (their macros
that do the casting for you do some sort of check first though)
| The compiler may add padding between elements of the struct for
| alignment purposes, but we don't need to care about that
| (sizeof(struct foo)) will do the right thing. If you don't believe
| me, ask the guru's on comp.lang.c. This extra space allocation for
| structs trick, only works for the last member of the struct
| (obviously), and it should be declared as an array with one element
| (it's not limited to char's).
Though technically that 'len' should be multiplied by 'sizeof(char)'
just for safety/clarity (even though sizeof(char) is 1).
| > > The benefit is being able to use one malloc vs. two (for any similarly
| >
| > This is a benefit why? :}
|
| Calls to malloc are relatively expensive. It's more efficient to use
| fewer large allocations than many small ones. Also, makes management
| of the memory a little simpler (only one chunk of memory to worry about).
I was thinking of the redundancy of calling realloc() shortly after
calling malloc(), but I had something different (but not wholly clear)
in mind.
-D
--
Consider what God has done:
Who can straighten what He has made crooked?
Ecclesiastes 7:13
Reply to: