A cast question

J

Jack

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
 
I

Ian Collins

Jack said:
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;
 
P

Prathamesh Kulkarni

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 *)); ?
 
B

Ben Bacarisse

Jack said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top