offset of a member inside a structure

J

junky_fellow

I am trying to find the offset of a member "mbr" inside a structure
"str" as follows:

offset = &(struct str *)0->mbr;

But, on compilation I get the following error:
cc: Error: m1.c, line 55: In this statement, "0" has a signed int
type, but occurs in a context that requires a pointer. (needpointer)

Can anybody point out where the problem is ?

Thanx for any help in advance....
 
C

Chris Dollin

junky_fellow said:
I am trying to find the offset of a member "mbr" inside a structure
"str" as follows:

offset = &(struct str *)0->mbr;

But, on compilation I get the following error:
cc: Error: m1.c, line 55: In this statement, "0" has a signed int
type, but occurs in a context that requires a pointer. (needpointer)

Can anybody point out where the problem is ?

Yes. You're not using the offsetof macro from <stddef.h>.

[The expression `(type) foo->bar` parses as `(type) (foo->bar)`. You
needed `&((struct str *)0)->mbr` for what you were trying to do.
However, what you're trying to do (a) has undefined behaviour and
(b) doesn't return what I (at least) think of as the "offset" of
a member, in plausible implementations. What, exactly, *are* you
trying to do?]
 
K

Kenneth Brody

junky_fellow said:
I am trying to find the offset of a member "mbr" inside a structure
"str" as follows:

offset = &(struct str *)0->mbr;

But, on compilation I get the following error:
cc: Error: m1.c, line 55: In this statement, "0" has a signed int
type, but occurs in a context that requires a pointer. (needpointer)

Can anybody point out where the problem is ?

I believe that "->" has higher precedence than the cast. (Though if
I'm wrong, someone will be along shortly to correct that.)

Try:

offset = &(((struct str *)0)->mbr);

My C compiler has:

#define offsetof(__typ,__id) ((size_t)&(((__typ*)0)->__id))
 
M

Michael Mair

Hi Chris,


Chris said:
junky_fellow wrote:

I am trying to find the offset of a member "mbr" inside a structure
"str" as follows:

offset = &(struct str *)0->mbr;

But, on compilation I get the following error:
cc: Error: m1.c, line 55: In this statement, "0" has a signed int
type, but occurs in a context that requires a pointer. (needpointer)

Can anybody point out where the problem is ?


Yes. You're not using the offsetof macro from <stddef.h>.

[The expression `(type) foo->bar` parses as `(type) (foo->bar)`. You
needed `&((struct str *)0)->mbr` for what you were trying to do.
However, what you're trying to do (a) has undefined behaviour and
(b) doesn't return what I (at least) think of as the "offset" of
a member, in plausible implementations. What, exactly, *are* you
trying to do?]

Well, apart from the fact that the standard headers can of course
do what they want in an implementation defined way as long as they
provide what the standard demands in the way the standard demands:
In most implementations I know you find offsetof to be defined along
the lines of
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
with differences mainly in the size_t typecast.

So, maybe the OP has seen this somewhere and wanted to reproduce it.

BTW: Does this really invoke UB?


Cheers
Michael
 
C

Chris Dollin

Michael said:
Hi Chris,
Chris said:
junky_fellow wrote:

I am trying to find the offset of a member "mbr" inside a structure
"str" as follows:

offset = &(struct str *)0->mbr;

But, on compilation I get the following error:
cc: Error: m1.c, line 55: In this statement, "0" has a signed int
type, but occurs in a context that requires a pointer. (needpointer)

Can anybody point out where the problem is ?


Yes. You're not using the offsetof macro from <stddef.h>.

[The expression `(type) foo->bar` parses as `(type) (foo->bar)`. You
needed `&((struct str *)0)->mbr` for what you were trying to do.
However, what you're trying to do (a) has undefined behaviour and
(b) doesn't return what I (at least) think of as the "offset" of
a member, in plausible implementations. What, exactly, *are* you
trying to do?]

Well, apart from the fact that the standard headers can of course
do what they want in an implementation defined way as long as they
provide what the standard demands in the way the standard demands:

More importantly, an implementation's standard headers can assume
properties of that implementation ...
In most implementations I know you find offsetof to be defined along
the lines of
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
with differences mainly in the size_t typecast.

So, maybe the OP has seen this somewhere and wanted to reproduce it.

BTW: Does this really invoke UB?

I believe so, but the last time I remember going round the discussion,
it depended on exactly how much wiggle-room one thought there was in
the Standard, and whether the expression

&pointer->member

had to be viewed as dereferencing `pointer`.

My view is: I would not do that, unless I had to; if I had to, I would
document that I did it and put tests in the test-suite to guard it; I
would expect it to work on most any platform I actually used, whether or
not I used it.

And for getting offsets, I would use offsetof. Why make trouble for
oneself, when there's already enough to hand?
 
F

Fred L. Kleinschmidt

junky_fellow said:
I am trying to find the offset of a member "mbr" inside a structure
"str" as follows:

offset = &(struct str *)0->mbr;

But, on compilation I get the following error:
cc: Error: m1.c, line 55: In this statement, "0" has a signed int
type, but occurs in a context that requires a pointer. (needpointer)

Can anybody point out where the problem is ?

Thanx for any help in advance....

As the error message states, 0 is an int, not a pointer. Use NULL.
 
M

Michael Mair

Chris said:
Michael said:
Chris said:
junky_fellow wrote:

I am trying to find the offset of a member "mbr" inside a structure
"str" as follows:

offset = &(struct str *)0->mbr;

But, on compilation I get the following error:
cc: Error: m1.c, line 55: In this statement, "0" has a signed int
type, but occurs in a context that requires a pointer. (needpointer)

Can anybody point out where the problem is ?


Yes. You're not using the offsetof macro from <stddef.h>.

[The expression `(type) foo->bar` parses as `(type) (foo->bar)`. You
needed `&((struct str *)0)->mbr` for what you were trying to do.
However, what you're trying to do (a) has undefined behaviour and
(b) doesn't return what I (at least) think of as the "offset" of
a member, in plausible implementations. What, exactly, *are* you
trying to do?]

Well, apart from the fact that the standard headers can of course
do what they want in an implementation defined way as long as they
provide what the standard demands in the way the standard demands:

More importantly, an implementation's standard headers can assume
properties of that implementation ...

Should have written it that way... Thanks for putting it
more clearly :)

I believe so, but the last time I remember going round the discussion,
it depended on exactly how much wiggle-room one thought there was in
the Standard, and whether the expression

&pointer->member

had to be viewed as dereferencing `pointer`.

Okay, so it is open to some debate. I just looked at it and thought
"With some imagination it does not even dereference anything, gives
you ptrdiff_t or whatever you need... Could work".
The discussions you probably referred to (I googled for offsetof in
comp.lang.c and comp.std.c and had a look at the first ten hits)
basically say(*) it is UB but works most of the time.

My view is: I would not do that, unless I had to; if I had to, I would
document that I did it and put tests in the test-suite to guard it; I
would expect it to work on most any platform I actually used, whether or
not I used it.

And for getting offsets, I would use offsetof. Why make trouble for
oneself, when there's already enough to hand?

Yes, of course -- I do not disagree; I was just puzzled as I could
not derive from the standard whether it works always and everywhere.


Cheers
Michael

(*) Read: The comments of the regulars I trust to know the standard
very well and certainly better than me tend on average to say...
 
R

Richard Tobin

Fred L. Kleinschmidt said:
As the error message states, 0 is an int, not a pointer. Use NULL.

That's not the problem. Others have correctly explained it.

Changing the 0 to NULL does not change the error message on the system
I use, nor on many others. Which is not surprising, since it has

#define NULL 0

in stdio.h.

-- Richard
 
D

Dan Pop

As the error message states, 0 is an int, not a pointer. Use NULL.

Don't be idiot! NULL may as well expand to a plain 0. The "right"
fix is to add the badly needed parentheses. And the right fix is to use
the offsetof macro instead. That's one wheel of the standard C library
that is best not reinvented.

Dan
 
M

Mark F. Haigh

Chris said:
Michael Mair wrote:


I believe so, but the last time I remember going round the discussion,
it depended on exactly how much wiggle-room one thought there was in
the Standard, and whether the expression

&pointer->member

had to be viewed as dereferencing `pointer`.
<snip>

Implementations are allowed to be stupid, even if the stupidity borders
on maliciousness. If compiled and executed on the Deathstation 9000,
for example, this statement causes nuclear war, unfortunately.

In all seriousness, the consensus was that it invokes undefined behavior.



Mark F. Haigh
(e-mail address removed)
 
T

Tim Rentsch

My comment here is mainly about this definition. I understand
that normally it's better to use an implementation-supplied
'offsetof()' rather than writing one's own. However, if one
were to want to write one, would not the definition

#define offsetof(TYPE,MEMBER) \
((size_t) ( \
(char*) &((TYPE *)0)->MEMBER - (char*) &(*(TYPE *)0) \
))

be more likely to yield more-portably correct results?

I believe so, but the last time I remember going round the discussion,
it depended on exactly how much wiggle-room one thought there was in
the Standard, and whether the expression

&pointer->member

had to be viewed as dereferencing `pointer`.

Presumably if one definition invokes UB then the other does (and vice
versa?). That notwithstanding, however (or alternatively, if one were
writing 'offsetof()' as part of a C implementation), doesn't the
subtractive definition seem a little cleaner than the earlier one?
 
C

Chris Torek

... I understand
that normally it's better to use an implementation-supplied
'offsetof()' rather than writing one's own. However, if one
were to want to write one, would not the definition

#define offsetof(TYPE,MEMBER) \
((size_t) ( \
(char*) &((TYPE *)0)->MEMBER - (char*) &(*(TYPE *)0) \
))

be more likely to yield more-portably correct results?

Aside from the extra "&", this is the one in the comp.lang.c FAQ
(question 2.14).
Presumably if one definition invokes UB then the other does (and vice
versa?). That notwithstanding, however (or alternatively, if one were
writing 'offsetof()' as part of a C implementation), doesn't the
subtractive definition seem a little cleaner than the earlier one?

Implementors are, of course, allowed to be "arbitrarily dirty" since
they (presumably) control the horizontal and the vertical. Perhaps
offsetof() is #define'd as:

#define offsetof(t, f) _O_O_(f, t)

for instance. :) The subtractive version would in general remove
any "nonzero null pointer bias" that might be left behind without
the subtraction, but one would certainly hope that the implementor
knows how he implemented his null pointers.
 
T

Tim Rentsch

Chris Torek said:
Aside from the extra "&", this is the one in the comp.lang.c FAQ
(question 2.14).

Ahh, I'd forgotten that. It makes sense though.

Implementors are, of course, allowed to be "arbitrarily dirty" since
they (presumably) control the horizontal and the vertical. Perhaps
offsetof() is #define'd as:

#define offsetof(t, f) _O_O_(f, t)

for instance. :) The subtractive version would in general remove
any "nonzero null pointer bias" that might be left behind without
the subtraction, but one would certainly hope that the implementor
knows how he implemented his null pointers.

Right. I admit it's a fine distinction. It just seems like people
would want to choose a definition that's more likely to work in the
_next_ implementation; in fact I would expect the subtractive
definition to work in any implementation unless the compiler made an
effort to thwart it. Also the subtractive definition has educational
value - it serves as a reminder that null pointers don't necessarily
have the value zero, and we can expect that new C programmers will
(occasionally) read definitions of 'offsetof()' and get that notion
reinforced.

Can you tell that I'm someone who believes in defensive safe
coding practices? :)

Thank you Chris for your comments.
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top