468,457 Members | 1,685 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,457 developers. It's quick & easy.

offsetof macro and non-POD structures. Solution.

Hallo group members.

//p1.cpp
#include <stdio.h>
#include <linux/stddef.h>

struct Person {
int m_age;
char* m_name;
};

struct Child: public Person {
unsigned short m_school_year;
};

int main()
{
printf ("offset to m_name: %d\n", offsetof(Child, m_name));
printf ("offset to m_length: %d\n", offsetof(Child, m_school_year));
}

As You know the program above compiles with a warning:
prompt$ g++ -g -O0 -o /tmp/p1 p1.cpp

p1.cpp: In function `int main()':
p1.cpp:16: warning: invalid access to non-static data member `Person::m_name' of NULL object
p1.cpp:16: warning: (perhaps the `offsetof' macro was used incorrectly)
p1.cpp:17: warning: invalid access to non-static data member `Child::m_school_year' of NULL object
p1.cpp:17: warning: (perhaps the `offsetof' macro was used incorrectly)
As I read in this newsgroup, the reason is casting 0 to address non-POD structure.
Indeed, the following code produces the same warning:

int main()
{
#define BASE 0x0
printf ( "m_name: %d\n", &((Child*)BASE)->m_school_year );
}

My question is: can I safely ignore this warning for structures of the complexity above?

Again, I found in this newsgroup that solution would be just to turn off this warning
with -Wno-invalid-offsetof flag.

Another solution is, if BASE != 0, then warning is not produced, so that would be the solution.

offsetof macro would look like following:
#define OFFSETOF_BASE 0x1
#define Offsetof(TYPE, MEMBER) \
(size_t)((unsigned char*)(&(((TYPE*)OFFSETOF_BASE)->MEMBER)) - (unsigned char*)(TYPE*)OFFSETOF_BASE)

Regards,
Pawel
Oct 18 '06 #1
8 5458
Pawel <nu***@wp.plwrote:
Hallo group members.

//p1.cpp
#include <stdio.h>
#include <linux/stddef.h>
This is wrong; it should be <stddef.h>, without the linux.
struct Person {
int m_age;
char* m_name;
};

struct Child: public Person {
This is not C. (And it's not C++, either, because then both headers
above would be wrong.)
unsigned short m_school_year;
};

int main()
{
printf ("offset to m_name: %d\n", offsetof(Child, m_name));
This is wrong; there is no Child, and struct Child has no member called
m_name in C. It may in C++, but for information on that you need to ask
in comp.lang.c++, not here.
printf ("offset to m_length: %d\n", offsetof(Child, m_school_year));
If corrected to read struct Child, this is almost correct.

Both printf() statements also print a size_t, which is unsigned and of
unknown width, using %d. That, too, is wrong. You should either cast
offsetof() to unsigned long and use %lu, or use a C99 implemetation and
%zu. This is not likely to be your underlying problem, but it's still
wrong.
}

As You know the program above compiles with a warning:
Do I? As you _should_ know, different compilers issue different warnings
for different problems.
prompt$ g++ -g -O0 -o /tmp/p1 p1.cpp

p1.cpp: In function `int main()':
p1.cpp:16: warning: invalid access to non-static data member `Person::m_name' of NULL object
p1.cpp:16: warning: (perhaps the `offsetof' macro was used incorrectly)
p1.cpp:17: warning: invalid access to non-static data member `Child::m_school_year' of NULL object
p1.cpp:17: warning: (perhaps the `offsetof' macro was used incorrectly)
Neither of those make complete sense in a C context, but the latter a
bit more than the former.
In any case, with the two corrections I mentioned above, your _last_
call of offsetof() would be correct C, and should, for a non-broken
implementation, not give warnings. In theory an implementation is
allowed to print whatever warnings it likes, but as a QoI issue, it
ought not to for this case.
As I read in this newsgroup, the reason is casting 0 to address non-POD structure.
What is an "address non-POD structure"?

In any case, the offsetof() that got delivered with your implementation
in <stddef.h(_not_ <linux/stddef.h>!) should be usable without
warnings. If not, that is IMO a bug in the implementation, and you
should complain to your supplier.
Indeed, the following code produces the same warning:

int main()
{
#define BASE 0x0
printf ( "m_name: %d\n", &((Child*)BASE)->m_school_year );
}
Why not simply use NULL?
My question is: can I safely ignore this warning for structures of the complexity above?
No. The warning means that _you_ can't safely do this, on this
implementation. If you get that same warning for the normal, ISO C
offsetof() macro, the warning means that your implementation is broken.
Again, I found in this newsgroup that solution would be just to turn off this warning
with -Wno-invalid-offsetof flag.
That's as may be, but that is an implementation-dependent solution, and
I could not possibly comment on its value.
Another solution is, if BASE != 0, then warning is not produced, so that would be the solution.

offsetof macro would look like following:
#define OFFSETOF_BASE 0x1
#define Offsetof(TYPE, MEMBER) \
(size_t)((unsigned char*)(&(((TYPE*)OFFSETOF_BASE)->MEMBER)) - (unsigned char*)(TYPE*)OFFSETOF_BASE)
That, however, replaces a warning with definite undefined behaviour, and
is therefore a cure worse than the problem. Don't do this at all; you
may be inviting your program to crash at the most inopportune moment.
Instead, make sure that you get a full, correct implementation; in
particular, make sure that your headers and your compiler fit together,
and that you use the correct headers, not after-market ones.

Richard
Oct 18 '06 #2
Pawel wrote:
Hallo group members.

//p1.cpp
^^^^
Probably not a C translation unit. If not, it is not topical in comp.lang.c
#include <stdio.h>
#include <linux/stddef.h>
^^^^^^^^^^^^^^^^
implementation specific header, so not topical in comp.lang.c. If there
a reason not to use the topical <stddef.h>?
>
struct Person {
int m_age;
char* m_name;
};

struct Child: public Person {
^^^^^^^^^^^^^
':' syntax error
'public' undefined identifier
*Certainly* not topical in comp.lang.c. Are you perhaps confused,
thinking that the different programming language C++ should be of the
slightest interest in comp.lang.c?
[remaining silliness removed]
Oct 18 '06 #3
Richard Bos wrote:
Pawel <nu***@wp.plwrote:
#include <stdio.h>
#include <linux/stddef.h>

This is wrong; it should be <stddef.h>, without the linux.
struct Person {
int m_age;
char* m_name;
};

struct Child: public Person {

This is not C. (And it's not C++, either, because then both headers
above would be wrong.)

While the C-headers such as <stdio.hare deprecated in C++, they are
standard. In fact, I suspect that they will persist through many more
revisions of the C++ standard.


Brian
Oct 18 '06 #4
Default User <de***********@yahoo.comwrote:

(crossposted to comp.lang.c++, f'ups set)
While the C-headers such as <stdio.hare deprecated in C++, they are
standard. In fact, I suspect that they will persist through many more
revisions of the C++ standard.
I gather that the rest of the headers held over from C (<string.h>,
<stdlib.h>, etc.) are also standard?

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
Oct 18 '06 #5
"Default User" <de***********@yahoo.comwrote:
Richard Bos wrote:
Pawel <nu***@wp.plwrote:
#include <stdio.h>
#include <linux/stddef.h>
This is wrong; it should be <stddef.h>, without the linux.
struct Person {
int m_age;
char* m_name;
};
>
struct Child: public Person {
This is not C. (And it's not C++, either, because then both headers
above would be wrong.)

While the C-headers such as <stdio.hare deprecated in C++, they are
standard. In fact, I suspect that they will persist through many more
revisions of the C++ standard.
I was under the impression that they're supposed to be called <cstdio.h>
or something like that?

Richard
Oct 19 '06 #6
Richard Bos said:
"Default User" <de***********@yahoo.comwrote:
<snip>
>>
While the C-headers such as <stdio.hare deprecated in C++, they are
standard. In fact, I suspect that they will persist through many more
revisions of the C++ standard.

I was under the impression that they're supposed to be called <cstdio.h>
or something like that?
Yes, the latter. :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 19 '06 #7
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
"Default User" <de***********@yahoo.comwrote:
[snip]
>While the C-headers such as <stdio.hare deprecated in C++, they are
standard. In fact, I suspect that they will persist through many more
revisions of the C++ standard.

I was under the impression that they're supposed to be called <cstdio.h>
or something like that?
I don't know, but I'm sure the folks in comp.lang.c++ do.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Oct 19 '06 #8
Richard Bos wrote:
"Default User" <de***********@yahoo.comwrote:
While the C-headers such as <stdio.hare deprecated in C++, they
are standard. In fact, I suspect that they will persist through
many more revisions of the C++ standard.

I was under the impression that they're supposed to be called
<cstdio.hor something like that?
See my message elsethread about this. Otherwise, drop me email or we
could continue this on clc++.


Brian
Oct 19 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by Hiroki Horiuchi | last post: by
6 posts views Thread by Arthur J. O'Dwyer | last post: by
44 posts views Thread by Simon Morgan | last post: by
13 posts views Thread by luke | last post: by
7 posts views Thread by Fred Zwarts | last post: by
11 posts views Thread by Kavya | last post: by
24 posts views Thread by Francine.Neary | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.