Velocity Reviews > Struct casting

# Struct casting

Ben Pfaff
Guest
Posts: n/a

 12-05-2011
Edward Rutherford <(E-Mail Removed)> writes:

> Who is right here by the letter of the law?

standard:

A pointer to a structure object, suitably converted, points
to its initial member (or if that member is a bit-field,
then to the unit in which it resides), and vice versa.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1utchar(a[i&15]);break;}}}

jacob navia
Guest
Posts: n/a

 12-06-2011
Le 05/12/11 22:52, Edward Rutherford a écrit :
> This was pulled up at a code review. Code was similar to this:
>
> struct foo {
> int bar;
> int baz;
> } f;
>
> int * i = (int *) f;
>
> The only way this could go wrong is if the struct contains padding before
> its first member, but I don't think this would ever happen in practice
> --- maybe on theoretical perverse implementations like the ones you guys
> like to play with
>
> Who is right here by the letter of the law?
>
> Cheers
> Edward

This is a mistake. Instead of writing

int *i = &f.bar; // 16 characters

you write

int * i = (int *) f; // 20 characters

AND (most important):

Now, the "bar" member MUST be the first member of the
structure! And, as Murphy's Law states, sombody will
add a member to the struct foo in the new version,
2 years from here.

WHO will remember that in another file there was an
implicit dependency as to "bar" being the first member?

This code is unmaintainable, it provokes a bug if
ANY modification is done to "bar" within the structure.

Suppose that "bar" member is eliminated. Instead of
provokinbg a compiler error and forcing you to change
the dependent code, the code will silently compile
and provoke a VERY hard debugging session.

I see no justification whatsoever for writing code
like that.

jacob

P.S. Anyway your code doesn't compile, as others have said.

Malcolm McLean
Guest
Posts: n/a

 12-06-2011
On Dec 6, 9:29*am, jacob navia <(E-Mail Removed)> wrote:
>
> int * i = (int *) f; // 20 characters
>
> I see no justification whatsoever for writing code
> like that.
>

As the snippet goes, no.

But "bar" might in fact be type a identifier field

foodoo(struct foo *f)
{
switch( *( int *) f)
{
case REALLYABAR:
dobar(f); return;
case REALLYAFOO:
dofoo(f); return;
}
}

This is arguably better than switch(foo->bar) because it makes clear
that code will onyl work if the identifier is the first member.

Ian Collins
Guest
Posts: n/a

 12-06-2011
On 12/ 6/11 09:15 PM, Malcolm McLean wrote:
> On Dec 6, 9:29 am, jacob navia<(E-Mail Removed)> wrote:
>>
>> int * i = (int *) f; // 20 characters
>>
>> I see no justification whatsoever for writing code
>> like that.
>>

> As the snippet goes, no.
>
> But "bar" might in fact be type a identifier field
>
> foodoo(struct foo *f)
> {
> switch( *( int *) f)
> {
> case REALLYABAR:
> dobar(f); return;
> case REALLYAFOO:
> dofoo(f); return;
> }
> }
>
> This is arguably better than switch(foo->bar) because it makes clear
> that code will onyl work if the identifier is the first member.

Better still is to give the first member a name that identifies is as
the type identifier field. The X XEvent union is a good example of this.

--
Ian Collins

Lauri Alanko
Guest
Posts: n/a

 12-06-2011
In article <(E-Mail Removed)>,
Keith Thompson <(E-Mail Removed)> wrote:
> There cannot be any padding before the first member. The code is safe,
> but poor style. Presumably the member "bar" was given a name for a
> reason; just use that name:
>
> int *i = &f.bar;
>
> Unless, for some odd reason, you specifically want the address of
> the first member of the struct, and you're sure it's an int without
> being sure of its name.

It's a common idiom to simulate poor man's subtyping for structs by
placing the supertype struct as the first member of the subtype
struct, and then casting between struct pointer types. It may even be
that the members of the structs are hidden from client code (or at
least considered private), so the public interface might only say that
a subtype struct pointer can be cast to the supertype pointer (and
back again) without saying anything about the names of the members.

Then again, the direct address-of-member approach, along with a
containerof macro, gives you multiple inheritance, which might be
useful.

Lauri

Joe keane
Guest
Posts: n/a

 12-08-2011
In article <jbjeed\$c1v\$(E-Mail Removed)>,
Edward Rutherford <(E-Mail Removed)> wrote:
>Who is right here by the letter of the law?

Letter of law, 'good idea' is often different.

It's right, but when someone comes along and mofidies your code,
is it likely to do what they expect?

Of course you put a comment that that member needs to be first, right?