Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #29104 > unrolled thread

A cast question

Started byJack <junw2000@gmail.com>
First post2012-12-09 23:30 -0800
Last post2012-12-10 12:47 +0000
Articles 4 — 4 participants

Back to article view | Back to comp.lang.c


Contents

  A cast question Jack <junw2000@gmail.com> - 2012-12-09 23:30 -0800
    Re: A cast question Ian Collins <ian-news@hotmail.com> - 2012-12-10 21:00 +1300
    Re: A cast question Prathamesh Kulkarni <bilbotheelffriend@gmail.com> - 2012-12-10 03:39 -0800
    Re: A cast question Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-10 12:47 +0000

#29104 — A cast question

FromJack <junw2000@gmail.com>
Date2012-12-09 23:30 -0800
SubjectA cast question
Message-ID<16311418-f133-4115-bb15-92575637d2c3@googlegroups.com>
In the following code (taken from a book):

struct Class {
   size_t size;
   void * (* ctor) (void * self, va_list * app);
   void * (* dtor) (void * self);
   void * (* clone) (const void * self);
   int (* differ) (const void * self, const void * b);
};

void * new (const void * _class, ...)
{ 
   const struct Class * class = _class;
   void * p = calloc(1, class —> size);

   * (const struct Class **) p = class;        //LINE1
  if (class —> ctor)
  {  va_list ap;
     va_start(ap, _class);
     p = class —> ctor(p, & ap);
     va_end(ap);
  }
  return p;
}

At LINE1, why cast P to (const struct Class **) first, then deference it? 
Is not LINE1 equal to the following line?

   (const struct Class *) p = class;


Thanks.

Jack

[toc] | [next] | [standalone]


#29107

FromIan Collins <ian-news@hotmail.com>
Date2012-12-10 21:00 +1300
Message-ID<ailj5nFq3nrU2@mid.individual.net>
In reply to#29104
Jack wrote:
> In the following code (taken from a book):
>
> struct Class {
>     size_t size;
>     void * (* ctor) (void * self, va_list * app);
>     void * (* dtor) (void * self);
>     void * (* clone) (const void * self);
>     int (* differ) (const void * self, const void * b);
> };
>
> void * new (const void * _class, ...)
> {
>     const struct Class * class = _class;
>     void * p = calloc(1, class —> size);
>
>     * (const struct Class **) p = class;        //LINE1
>    if (class —> ctor)
>    {  va_list ap;
>       va_start(ap, _class);
>       p = class —> ctor(p, & ap);
>       va_end(ap);
>    }
>    return p;
> }
>
> At LINE1, why cast P to (const struct Class **) first, then deference it?
> Is not LINE1 equal to the following line?
>
>     (const struct Class *) p = class;

No, the above isn't valid syntax (see the earlier "Casts on lvalues" 
thread for the gore).  Even if it were valid, it would change the value 
of p rather than saving the value of class in the memory pointed to by p.

They could have written

   const struct Class** p = calloc( 1, class->size );

   *p = class;

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#29114

FromPrathamesh Kulkarni <bilbotheelffriend@gmail.com>
Date2012-12-10 03:39 -0800
Message-ID<224a4d8f-762b-4ed0-b97e-c60516c30acd@googlegroups.com>
In reply to#29104
On Monday, 10 December 2012 02:30:43 UTC-5, Jack  wrote:
> In the following code (taken from a book):
> 
> 
> 
> struct Class {
> 
>    size_t size;
> 
>    void * (* ctor) (void * self, va_list * app);
> 
>    void * (* dtor) (void * self);
> 
>    void * (* clone) (const void * self);
> 
>    int (* differ) (const void * self, const void * b);
> 
> };
> 
> 
> 
> void * new (const void * _class, ...)
> 
> { 
> 
>    const struct Class * class = _class;
> 
>    void * p = calloc(1, class —> size);
> 
> 
> 
>    * (const struct Class **) p = class;        //LINE1

If you intend to use p as pointer to pointer to 
struct Class, shouldn't it be
void *p = calloc(1, sizeof(struct Class *)); ?

> 
>   if (class —> ctor)
> 
>   {  va_list ap;
> 
>      va_start(ap, _class);
> 
>      p = class —> ctor(p, & ap);
> 
>      va_end(ap);
> 
>   }
> 
>   return p;
> 
> }
> 
> 
> 
> At LINE1, why cast P to (const struct Class **) first, then deference it? 
> 
> Is not LINE1 equal to the following line?
> 
> 
> 
>    (const struct Class *) p = class;
> 
> 
> 
> 
> 
> Thanks.
> 
> 
> 
> Jack

[toc] | [prev] | [next] | [standalone]


#29117

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-12-10 12:47 +0000
Message-ID<0.5e7819f471265492e26e.20121210124736GMT.877goqm5uf.fsf@bsb.me.uk>
In reply to#29104
Jack <junw2000@gmail.com> writes:

> In the following code (taken from a book):
>
> struct Class {
>    size_t size;
>    void * (* ctor) (void * self, va_list * app);
>    void * (* dtor) (void * self);
>    void * (* clone) (const void * self);
>    int (* differ) (const void * self, const void * b);
> };
>
> void * new (const void * _class, ...)
> { 
>    const struct Class * class = _class;
>    void * p = calloc(1, class —> size);
>
>    * (const struct Class **) p = class;        //LINE1
>   if (class —> ctor)
>   {  va_list ap;
>      va_start(ap, _class);
>      p = class —> ctor(p, & ap);
>      va_end(ap);
>   }
>   return p;
> }
>
> At LINE1, why cast P to (const struct Class **) first, then deference it? 
> Is not LINE1 equal to the following line?
>
>    (const struct Class *) p = class;

As has been said, no.  You can't assign to a cast expression.

But this code is pretty gruesome!  It would be much clearer if the
intent were made plain.  The idea is that every class instance starts
with a pointer to a struct describing the class.  There is no need to
lie about that -- you can "over allocate" perfectly legally, so the
author could have written:

  struct ClassInstance {
      struct Class *class;
  };

and in new:

  const struct Class *class = _class;
  struct ClassInstance *inst = calloc(1, class->size);
  inst->class = class;
  if (class->ctor)
  {  va_list ap;
     va_start(ap, _class);
     inst = class->ctor(inst, &ap);
     va_end(ap);
  }
  return inst;

(and I'd change the return type, too).

Depending on the rest of the code, it's possible that the lie (called
type punning) might even break on some odd architectures.

-- 
Ben.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web