Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #14337 > unrolled thread
| Started by | Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> |
|---|---|
| First post | 2011-12-05 21:52 +0000 |
| Last post | 2011-12-08 21:08 +0000 |
| Articles | 17 — 13 participants |
Back to article view | Back to comp.lang.c
Struct casting Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> - 2011-12-05 21:52 +0000
Re: Struct casting Harald van Dijk <truedfx@gmail.com> - 2011-12-05 13:58 -0800
Re: Struct casting Tobias Blass <tobiasblass@gmx.net> - 2011-12-05 22:00 +0000
Re: Struct casting Ian Collins <ian-news@hotmail.com> - 2011-12-06 11:10 +1300
Re: Struct casting tom st denis <tom@iahu.ca> - 2011-12-05 14:06 -0800
Re: Struct casting Ian Collins <ian-news@hotmail.com> - 2011-12-06 11:11 +1300
Re: Struct casting James Kuyper <jameskuyper@verizon.net> - 2011-12-05 17:13 -0500
Re: Struct casting Robert Wessel <robertwessel2@yahoo.com> - 2011-12-05 16:10 -0600
Re: Struct casting Ian Collins <ian-news@hotmail.com> - 2011-12-06 11:13 +1300
Re: Struct casting James Kuyper <jameskuyper@verizon.net> - 2011-12-05 17:15 -0500
Re: Struct casting Keith Thompson <kst-u@mib.org> - 2011-12-05 14:16 -0800
Re: Struct casting Lauri Alanko <la@iki.fi> - 2011-12-06 18:00 +0000
Re: Struct casting blp@cs.stanford.edu (Ben Pfaff) - 2011-12-05 14:19 -0800
Re: Struct casting jacob navia <jacob@spamsink.net> - 2011-12-06 08:29 +0100
Re: Struct casting Malcolm McLean <malcolm.mclean5@btinternet.com> - 2011-12-06 00:15 -0800
Re: Struct casting Ian Collins <ian-news@hotmail.com> - 2011-12-06 22:30 +1300
Re: Struct casting jgk@panix.com (Joe keane) - 2011-12-08 21:08 +0000
| From | Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> |
|---|---|
| Date | 2011-12-05 21:52 +0000 |
| Subject | Struct casting |
| Message-ID | <jbjeed$c1v$1@speranza.aioe.org> |
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
[toc] | [next] | [standalone]
| From | Harald van Dijk <truedfx@gmail.com> |
|---|---|
| Date | 2011-12-05 13:58 -0800 |
| Message-ID | <9b516a84-fba4-4fbd-80b4-657fec875a06@z17g2000vbe.googlegroups.com> |
| In reply to | #14337 |
On Dec 5, 10:52 pm, Edward Rutherford
<edward.p.rutherfor...@REMOVETHIS.gmail.com> wrote:
> This was pulled up at a code review. Code was similar to this:
>
> struct foo {
> int bar;
> int baz;
>
> } f;
I'm assuming you meant } *f;
>
> int * i = (int *) f;
because otherwise this should be a hard error.
> 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
A pointer to a struct can be safely converted to a pointer to its
first member, and back. Padding before the first member is not
allowed.
That said, for various other reasons, relating to readability and
maintainability, it may well be better to just write
int *i = &f->bar;
[toc] | [prev] | [next] | [standalone]
| From | Tobias Blass <tobiasblass@gmx.net> |
|---|---|
| Date | 2011-12-05 22:00 +0000 |
| Message-ID | <jbjet4$dl3$1@dont-email.me> |
| In reply to | #14337 |
On 2011-12-05, Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> wrote:
> 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?
>
The standard guarantees that there is no padding before the first element, so
this conversion is absolutely valid. It may cause problems when another variable
is placed before the 'bar',though, and I wouldn't bet that the person that adds
the new member will change all these assignments.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-12-06 11:10 +1300 |
| Message-ID | <9k4tqhF18rU1@mid.individual.net> |
| In reply to | #14339 |
On 12/ 6/11 11:00 AM, Tobias Blass wrote:
> On 2011-12-05, Edward Rutherford<edward.p.rutherford79@REMOVETHIS.gmail.com> wrote:
>> 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?
>>
> The standard guarantees that there is no padding before the first element, so
> this conversion is absolutely valid.
Not as written. There's a * in the declaration f or an & in the
initialisation of i missing.
> It may cause problems when another variable
> is placed before the 'bar',though, and I wouldn't bet that the person that adds
> the new member will change all these assignments.
As mentioned else-thread,
int *i = &f->bar;
would be better.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | tom st denis <tom@iahu.ca> |
|---|---|
| Date | 2011-12-05 14:06 -0800 |
| Message-ID | <1ff2e759-cf81-4eee-8278-50a3992fb7d9@x7g2000yqb.googlegroups.com> |
| In reply to | #14337 |
On Dec 5, 4:52 pm, Edward Rutherford
<edward.p.rutherfor...@REMOVETHIS.gmail.com> wrote:
> 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?
Is there a question of alignment though?
Generally, that sort of code would fail review with me and my cohorts
[er...coworkers]. If you wanted a specific element of a struct you
should pick it by name.
Tom
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-12-06 11:11 +1300 |
| Message-ID | <9k4trmF18rU2@mid.individual.net> |
| In reply to | #14340 |
On 12/ 6/11 11:06 AM, tom st denis wrote:
> On Dec 5, 4:52 pm, Edward Rutherford
> <edward.p.rutherfor...@REMOVETHIS.gmail.com> wrote:
>> 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?
>
> Is there a question of alignment though?
No.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-12-05 17:13 -0500 |
| Message-ID | <4EDD4217.6010900@verizon.net> |
| In reply to | #14340 |
On 12/05/2011 05:06 PM, tom st denis wrote:
> On Dec 5, 4:52 pm, Edward Rutherford
> <edward.p.rutherfor...@REMOVETHIS.gmail.com> wrote:
>> 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?
>
> Is there a question of alignment though?
No, there is not. The standard guarantees that conversion of a pointer
to a struct to a pointer to the type of the first member produces a
valid pointer to that first member.
> Generally, that sort of code would fail review with me and my cohorts
> [er...coworkers]. If you wanted a specific element of a struct you
> should pick it by name.
Agreed. In addition to protecting against the possibility that bar might
be moved to a different position, it's also more type-safe, since a type
cast is no longer necessary.
[toc] | [prev] | [next] | [standalone]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2011-12-05 16:10 -0600 |
| Message-ID | <iufqd7l0lomlhch0hdich5psoepvvv5i6l@4ax.com> |
| In reply to | #14337 |
On Mon, 5 Dec 2011 21:52:13 +0000 (UTC), Edward Rutherford
<edward.p.rutherford79@REMOVETHIS.gmail.com> wrote:
>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?
FWIW, C++ compilers frequently put the vtable pointer at the beginning
of classes/structs that contain virtual functions (IOW, the "padding"
at the beginning of the struct would be the vtable pointer)..
In C, while two structures need to have the same layout in a common
leading area, I'm not sure there's a guarantee that the pointer to the
beginning of the beginning of the structure is required to be a
pointer to the first member.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-12-06 11:13 +1300 |
| Message-ID | <9k4tvrF18rU3@mid.individual.net> |
| In reply to | #14342 |
On 12/ 6/11 11:10 AM, Robert Wessel wrote:
> On Mon, 5 Dec 2011 21:52:13 +0000 (UTC), Edward Rutherford
> <edward.p.rutherford79@REMOVETHIS.gmail.com> wrote:
>
>> 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?
>
>
> FWIW, C++ compilers frequently put the vtable pointer at the beginning
> of classes/structs that contain virtual functions (IOW, the "padding"
> at the beginning of the struct would be the vtable pointer)..
>
> In C, while two structures need to have the same layout in a common
> leading area, I'm not sure there's a guarantee that the pointer to the
> beginning of the beginning of the structure is required to be a
> pointer to the first member.
There is.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-12-05 17:15 -0500 |
| Message-ID | <4EDD4269.8000502@verizon.net> |
| In reply to | #14342 |
On 12/05/2011 05:10 PM, Robert Wessel wrote: ... > In C, while two structures need to have the same layout in a common > leading area, I'm not sure there's a guarantee that the pointer to the > beginning of the beginning of the structure is required to be a > pointer to the first member. There is: 6.7.2.1p13.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-12-05 14:16 -0800 |
| Message-ID | <lnsjkyll5i.fsf@nuthaus.mib.org> |
| In reply to | #14337 |
Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes:
> This was pulled up at a code review. Code was similar to this:
>
> struct foo {
> int bar;
> int baz;
> } f;
>
> int * i = (int *) f;
That should be
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 :)
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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Lauri Alanko <la@iki.fi> |
|---|---|
| Date | 2011-12-06 18:00 +0000 |
| Message-ID | <jbll7e$ram$1@oravannahka.helsinki.fi> |
| In reply to | #14347 |
In article <lnsjkyll5i.fsf@nuthaus.mib.org>, Keith Thompson <kst-u@mib.org> 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
[toc] | [prev] | [next] | [standalone]
| From | blp@cs.stanford.edu (Ben Pfaff) |
|---|---|
| Date | 2011-12-05 14:19 -0800 |
| Message-ID | <87wraahda8.fsf@blp.benpfaff.org> |
| In reply to | #14337 |
Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes:
> Who is right here by the letter of the law?
Others already gave the answer. Here's the quote from the
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,0xa67f6aaa,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 1:putchar(a[i&15]);break;}}}
[toc] | [prev] | [next] | [standalone]
| From | jacob navia <jacob@spamsink.net> |
|---|---|
| Date | 2011-12-06 08:29 +0100 |
| Message-ID | <jbkg83$ad8$1@speranza.aioe.org> |
| In reply to | #14337 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2011-12-06 00:15 -0800 |
| Message-ID | <bebc7ea8-a1f8-48e9-b58c-dc669f6868bc@d10g2000vbf.googlegroups.com> |
| In reply to | #14349 |
On Dec 6, 9:29 am, jacob navia <ja...@spamsink.net> 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.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-12-06 22:30 +1300 |
| Message-ID | <9k65ksFuhiU2@mid.individual.net> |
| In reply to | #14350 |
On 12/ 6/11 09:15 PM, Malcolm McLean wrote:
> On Dec 6, 9:29 am, jacob navia<ja...@spamsink.net> 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
[toc] | [prev] | [next] | [standalone]
| From | jgk@panix.com (Joe keane) |
|---|---|
| Date | 2011-12-08 21:08 +0000 |
| Message-ID | <jbr8vg$3sb$1@reader1.panix.com> |
| In reply to | #14337 |
In article <jbjeed$c1v$1@speranza.aioe.org>, Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> 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?
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web