[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: