struct named 0
Collapse
This topic is closed.
X
X
-
Mohd Hanafiah AbdullahTags: None -
Michael Mair
Re: struct named 0
Mohd Hanafiah Abdullah wrote:
[color=blue]
> Is the following code conformat to ANSI C?
>
> typedef struct {
> int a;
> int b;
> } doomdata;
>
> int main(void)
> {
> int x;
>
> x = (int)&((doomdat a*)0)->b;
> printf("x=%d\n" , x);
> return x;
> }
>
> The part,
> (int)&((doomdat a*)0)->b;
>
> is it conformant to ANSI C? What is it supposed to do?[/color]
According to prior discussions, it is at least shady but
probably not conformant, depending on whether the address
0 is dereferenced or not.
This is a version of the offsetof macro from <stddef.h>:
offsetof(doomda ta,b)
gives you the byte offset of b in struct doomsdata, that means
if we have
struct doomdata d;
unsigned char *p = (unsigned char *)&d;
then the address of d.b is p+offsetof(doom data,b).
In contrast to offsetof which expands to an expression of
type size_t, the above will give you an int.
Use offsetof.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
-
S.Tobias
Re: struct named 0
Mohd Hanafiah Abdullah <napi@cs.indian a.edu> wrote:
[color=blue]
> typedef struct {
> int a;
> int b;
> } doomdata;[/color]
[color=blue]
> (int)&((doomdat a*)0)->b;[/color]
[color=blue]
> is it conformant to ANSI C?[/color]
IMO no, because it doesn't point to any valid object, so
invokes UB.
Question to others:
Would this be correct?
(int)&((doomdat a*)0)->a;
--
Stan Tobias
mailx `echo siXtY@FamOuS.Be dBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Comment
-
Malcolm
Re: struct named 0
"Mohd Hanafiah Abdullah" <napi@cs.indian a.edu> wrote[color=blue]
>
> The part,
> (int)&((doomdat a*)0)->b;
>
> is it conformant to ANSI C? What is it supposed to do?
>[/color]
This is the offsetof() macro, which calculates the offset of a structure
member relative to the struct origin.
On most platforms it works, but it suffers a few problems on unusual
systems. For instance, if NULL is not all bits zero, or if there are trap
pointer representations , then the method won't work naturally. So I believe
that in C89 it is not required to work.
Comment
-
Joona I Palaste
Re: struct named 0
Michael Mair <Michael.Mair@i nvalid.invalid> scribbled the following:[color=blue]
> Mohd Hanafiah Abdullah wrote:[color=green]
>> Is the following code conformat to ANSI C?
>>
>> typedef struct {
>> int a;
>> int b;
>> } doomdata;
>>
>> int main(void)
>> {
>> int x;
>>
>> x = (int)&((doomdat a*)0)->b;
>> printf("x=%d\n" , x);
>> return x;
>> }
>>
>> The part,
>> (int)&((doomdat a*)0)->b;
>>
>> is it conformant to ANSI C? What is it supposed to do?[/color][/color]
[color=blue]
> According to prior discussions, it is at least shady but
> probably not conformant, depending on whether the address
> 0 is dereferenced or not.
> This is a version of the offsetof macro from <stddef.h>:
> offsetof(doomda ta,b)
> gives you the byte offset of b in struct doomsdata, that means
> if we have
> struct doomdata d;
> unsigned char *p = (unsigned char *)&d;
> then the address of d.b is p+offsetof(doom data,b).
> In contrast to offsetof which expands to an expression of
> type size_t, the above will give you an int.[/color]
[color=blue]
> Use offsetof.[/color]
To be more specific, offsetof may be defined as the version mentioned by
the OP, but it doesn't have to be. However, whatever offsetof is defined
as, it is guaranteed to always be legal and valid code for that
particular implementation. The version mentioned by the OP may or may
not be valid and legal code, depending on the implementation.
--
/-- Joona Palaste (palaste@cc.hel sinki.fi) ------------- Finland --------\
\-------------------------------------------------------- rules! --------/
"The trouble with the French is they don't have a word for entrepreneur."
- George Bush
Comment
-
Jack Klein
Re: struct named 0
On Sun, 28 Nov 2004 11:26:06 +0100, Michael Mair
<Michael.Mair@i nvalid.invalid> wrote in comp.lang.c:
[color=blue]
> Mohd Hanafiah Abdullah wrote:
>[color=green]
> > Is the following code conformat to ANSI C?
> >
> > typedef struct {
> > int a;
> > int b;
> > } doomdata;
> >
> > int main(void)
> > {
> > int x;
> >
> > x = (int)&((doomdat a*)0)->b;
> > printf("x=%d\n" , x);
> > return x;
> > }
> >
> > The part,
> > (int)&((doomdat a*)0)->b;
> >
> > is it conformant to ANSI C? What is it supposed to do?[/color]
>
> According to prior discussions, it is at least shady but
> probably not conformant, depending on whether the address
> 0 is dereferenced or not.[/color]
No it has undefined behavior, and has nothing to do with the "address
0", but with a null pointer. C is defined in terms of an abstract
machine, and in the abstract machine this expression dereferences a
null pointer.
[color=blue]
> This is a version of the offsetof macro from <stddef.h>:
> offsetof(doomda ta,b)
> gives you the byte offset of b in struct doomsdata, that means
> if we have
> struct doomdata d;
> unsigned char *p = (unsigned char *)&d;
> then the address of d.b is p+offsetof(doom data,b).
> In contrast to offsetof which expands to an expression of
> type size_t, the above will give you an int.
>
> Use offsetof.[/color]
Yes, indeed. The implementation' s offsetof() macro might indeed
contain similar code, excepting the cast to int. But the
implementation is not constrained to follow the rules of the abstract
machine, only user programs are.
[color=blue]
> Cheers
> Michael[/color]
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
Comment
-
Jack Klein
Re: struct named 0
On 28 Nov 2004 10:41:21 GMT, "S.Tobias"
<siXtY@FamOuS.B edBuG.pAlS.INVA LID> wrote in comp.lang.c:
[color=blue]
> Mohd Hanafiah Abdullah <napi@cs.indian a.edu> wrote:
>[color=green]
> > typedef struct {
> > int a;
> > int b;
> > } doomdata;[/color]
>[color=green]
> > (int)&((doomdat a*)0)->b;[/color]
>[color=green]
> > is it conformant to ANSI C?[/color]
>
> IMO no, because it doesn't point to any valid object, so
> invokes UB.
>
> Question to others:
> Would this be correct?
> (int)&((doomdat a*)0)->a;[/color]
Technically it is still undefined behavior, as the semantics of the
expression dereference a null pointer.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
Comment
-
Jack Klein
Re: struct named 0
On Sun, 28 Nov 2004 10:53:23 -0000, "Malcolm"
<malcolm@55bank .freeserve.co.u k> wrote in comp.lang.c:
[color=blue]
>
> "Mohd Hanafiah Abdullah" <napi@cs.indian a.edu> wrote[color=green]
> >
> > The part,
> > (int)&((doomdat a*)0)->b;
> >
> > is it conformant to ANSI C? What is it supposed to do?
> >[/color]
> This is the offsetof() macro, which calculates the offset of a structure
> member relative to the struct origin.[/color]
No, it can't be the offsetof() macro. This expression specifically
yields an int, whereas the offsetof() macro yields a size_t. This
expression yields undefined behavior.
[color=blue]
> On most platforms it works, but it suffers a few problems on unusual
> systems. For instance, if NULL is not all bits zero, or if there are trap
> pointer representations , then the method won't work naturally. So I believe
> that in C89 it is not required to work.[/color]
When will people get it through their heads that it makes not a whit
of difference whether all bits zero happens to be a representation of
a null pointer on a particular platform?
The correspondence between an integer constant expression evaluating
to 0 and a null pointer is exactly the same as quite a few other
constant expressions, that is something that is evaluated and
substituted at compile-time and has nothing to do with run-time
values.
The conversion of a quoted string to an array of '\0' terminated
values is a compile-time conversion.
The conversion of escape sequences like '\n' and '\t' to their single
character equivalents in string or character constants is a
compile-time conversion.
The conversion of an integer constant expression evaluating to 0, or
such an expression cast to the type pointer-to-void, to a null pointer
constant is a compile-time conversion, not a run-time one.
If the one and only representation for a null pointer in a particular
implementation is 0xDEADBEEF, and such a value is returned by a call
to fopen(), for example, a comparison of that value against NULL or 0
will still be true.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
Comment
-
Jack Klein
Re: struct named 0
On Sun, 28 Nov 2004 08:50:39 +0000 (UTC), napi@cs.indiana .edu (Mohd
Hanafiah Abdullah) wrote in comp.lang.c:
[color=blue]
>
> Is the following code conformat to ANSI C?
>
> typedef struct {
> int a;
> int b;
> } doomdata;
>
> int main(void)
> {
> int x;
>
> x = (int)&((doomdat a*)0)->b;[/color]
No, the line above invokes undefined behavior, because it dereferences
a null pointer.
[color=blue]
> printf("x=%d\n" , x);
> return x;
> }
>
> The part,
> (int)&((doomdat a*)0)->b;
>
> is it conformant to ANSI C? What is it supposed to do?[/color]
No, it is most certainly not conforming. It might have been written
as an example, or it might have been written by someone who doesn't
know that the offsetof(struct _type,member_na me) macro defined in
<stddef.h> does the same thing in a conforming manner.
[color=blue]
> Thanks for any tips.
>
> Napi[/color]
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
Comment
-
Malcolm
Re: struct named 0
"Jack Klein" <jackklein@spam cop.net> wrote[color=blue]
>[color=green][color=darkred]
> > > The part,
> > > (int)&((doomdat a*)0)->b;
> > >
> > > is it conformant to ANSI C? What is it supposed to do?
> > >[/color]
> > This is the offsetof() macro, which calculates the offset of a structure
> > member relative to the struct origin.[/color]
>
> No, it can't be the offsetof() macro. This expression specifically
> yields an int, whereas the offsetof() macro yields a size_t. This
> expression yields undefined behavior.
>[/color]
This is true. int is not guaranteed to be big enough to hold the offset of a
structure element (!).[color=blue]
>
> When will people get it through their heads that it makes not a whit
> of difference whether all bits zero happens to be a representation of
> a null pointer on a particular platform?
>[/color]
Unfortunately it does make a difference.
For instance consider
char **list = calloc(N, sizeof(char *));
for(i=0;i<N;i++ )
if( someconditon() )
list[i] = malloc(10);
for(i=0;i<N;i++ )
free(list[i]);
Also consider if a null pointer is cast to an integral type, or if a pointer
derived by adding an offset to the null pointer is cast to an integer. This
cast is a simple bitwise conversion, so results will differ on a platform on
which NULL is not all bits zero.
However char *ptr = 0; will always set ptr to NULL, regardless of whether
the null pointer is all bits zero. Here you are correct.
Comment
-
Martin Ambuhl
Re: struct named 0
Mohd Hanafiah Abdullah wrote:
[color=blue]
>
> The part,
> (int)&((doomdat a*)0)->b;
>
> is it conformant to ANSI C? What is it supposed to do?
>[/color]
#include <stdio.h>
#include <stddef.h>
typedef struct
{
int a;
int b;
} doomdata;
int main(void)
{
int x;
#if 0
/* mha: the following is an attempt to mimic offsetof on an
implementation not having offsetof in <stddef.h> */
x = (int) &((doomdata *) 0)->b;
#endif
x = offsetof(doomda ta, b);
printf("x=%d\n" , x);
return 0; /* mha: returning x, when x is not one
of 0, EXIT_SUCCESS, or EXIT_FAILURE
is at best implementation-defined */
}
Comment
-
S.Tobias
Re: struct named 0
Jack Klein <jackklein@spam cop.net> wrote:[color=blue]
> On 28 Nov 2004 10:41:21 GMT, "S.Tobias"
> <siXtY@FamOuS.B edBuG.pAlS.INVA LID> wrote in comp.lang.c:[color=green]
> > Mohd Hanafiah Abdullah <napi@cs.indian a.edu> wrote:[/color][/color]
[color=blue][color=green][color=darkred]
> > > typedef struct {
> > > int a;
> > > int b;
> > > } doomdata;[/color][/color][/color]
[color=blue][color=green]
> > Would this be correct?
> > (int)&((doomdat a*)0)->a;[/color][/color]
[color=blue]
> Technically it is still undefined behavior, as the semantics of the
> expression dereference a null pointer.[/color]
(This deserves a separate thread, but since I asked the above
question here, I'll continue here too.)
As I understand the expression constitutes an access to the structure
member.
1. Does a member access constitute an access to the *whole* structure?
eg.:
struct A { int i; int _i; };
struct B { int i; float f; };
struct A a = {0};
struct B *pb = (struct B*)&a;
pb->i; //UB?
(*pb).i; //UB?
Do I access the first int sub-object in `a' only, or do I access
the whole object `a'?
2. I see certain similarity between structs and arrays (in fact,
both are called "aggregates ").
Why is it that for array:
&a[5];
doesn't constitute object access (6.5.3.2#3), whereas for struct:
&s.m;
&ps->m;
the expressions do constitute access?
Why is the language designed like this?
--
Stan Tobias
mailx `echo siXtY@FamOuS.Be dBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Comment
-
xarax
Re: struct named 0
"Jack Klein" <jackklein@spam cop.net> wrote in message
news:ov3kq09rfb aenc41iqbaeuoup 5f87nq68e@4ax.c om...[color=blue]
> On Sun, 28 Nov 2004 11:26:06 +0100, Michael Mair
> <Michael.Mair@i nvalid.invalid> wrote in comp.lang.c:
>[color=green]
> > Mohd Hanafiah Abdullah wrote:
> >[color=darkred]
> > > Is the following code conformat to ANSI C?
> > >
> > > typedef struct {
> > > int a;
> > > int b;
> > > } doomdata;
> > >
> > > int main(void)
> > > {
> > > int x;
> > >
> > > x = (int)&((doomdat a*)0)->b;
> > > printf("x=%d\n" , x);
> > > return x;
> > > }
> > >
> > > The part,
> > > (int)&((doomdat a*)0)->b;
> > >
> > > is it conformant to ANSI C? What is it supposed to do?[/color]
> >
> > According to prior discussions, it is at least shady but
> > probably not conformant, depending on whether the address
> > 0 is dereferenced or not.[/color]
>
> No it has undefined behavior, and has nothing to do with the "address
> 0", but with a null pointer. C is defined in terms of an abstract
> machine, and in the abstract machine this expression dereferences a
> null pointer.[/color]
/snip/
It does not dereference any pointer. The & cancels out
the ->.
btw: If the dereference actually happened, how could the
compiler figure out the address of an int that was produced
by the dereference?
Comment
-
Christian Bau
Re: struct named 0
In article <cod91t$ihn$1@n ews7.svr.pol.co .uk>,
"Malcolm" <malcolm@55bank .freeserve.co.u k> wrote:
[color=blue]
> Also consider if a null pointer is cast to an integral type, or if a pointer
> derived by adding an offset to the null pointer is cast to an integer. This
> cast is a simple bitwise conversion, so results will differ on a platform on
> which NULL is not all bits zero.[/color]
Not quite; a conversion from a pointer type to an integer does whatever
the implementation thinks is a good idea; usually the bits of the
representation are copied unchanged, but that is not necessarily so.
In C99, there seems to be an actual requirement that casting an integer
zero to a pointer type will produce a null pointer. If null pointers
don't have all bits zero, and an integer 0 has all bits zero, and
converting an integer 0 to a pointer produces a null pointer, then logic
says that this conversion cannot leave the bits unchanged.
Comment
-
Malcolm
Re: struct named 0
"Christian Bau" <christian.bau@ cbau.freeserve. co.uk> wrote[color=blue]
>
> In C99, there seems to be an actual requirement that casting an integer
> zero to a pointer type will produce a null pointer. If null pointers
> don't have all bits zero, and an integer 0 has all bits zero, and
> converting an integer 0 to a pointer produces a null pointer, then logic
> says that this conversion cannot leave the bits unchanged.
>[/color]
But in this case we are not casting an integer 0 to a pointer, but a null
pointer to an integer.
Comment
Comment