A cast question

Discussion in 'C Programming' started by Jack, Dec 10, 2012.

  1. Jack

    Jack Guest

    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
    Jack, Dec 10, 2012
    #1
    1. Advertising

  2. Jack

    Ian Collins Guest

    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
    Ian Collins, Dec 10, 2012
    #2
    1. Advertising

  3. 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
    Prathamesh Kulkarni, Dec 10, 2012
    #3
  4. Jack <> 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.
    Ben Bacarisse, Dec 10, 2012
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VB Programmer

    Question: Invalid Cast Exception Error

    VB Programmer, Oct 28, 2003, in forum: ASP .Net
    Replies:
    4
    Views:
    1,340
    VB Programmer
    Oct 28, 2003
  2. Christopher Benson-Manica

    Quick cast style question

    Christopher Benson-Manica, Apr 30, 2004, in forum: C++
    Replies:
    15
    Views:
    518
    Jake Montgomery
    May 4, 2004
  3. MSG

    to cast or not to cast malloc ?

    MSG, Feb 6, 2004, in forum: C Programming
    Replies:
    38
    Views:
    1,046
    Dan Pop
    Feb 10, 2004
  4. EvilRix
    Replies:
    8
    Views:
    605
    Martin Dickopp
    Feb 14, 2004
  5. Pavel
    Replies:
    7
    Views:
    503
    Pavel
    Sep 19, 2010
Loading...

Share This Page