Trouble with offsetof

Discussion in 'C++' started by Exits Funnel, Jan 8, 2005.

  1. Exits Funnel

    Exits Funnel Guest

    Consider this code which is a very trimmed down version of some I've
    inherited and am trying to port from windows to g++:

    //Begin test1.cpp
    class foo { int i; int j; };

    class bar
    {
    bar (int foo::* dataMember)
    :eek:ffsetof (foo, *dataMember) //Call this Line (A)
    {
    // int i = offsetof (foo, *dataMember); //Call this Line (B)
    }
    };
    //End test1.cpp

    when I try to compile test1.cpp with g++, the compiler has this to say:

    test2.cpp: In constructor `bar::bar(int foo::*)':
    test2.cpp:6: syntax error before `;' token

    A couple of questions then:

    (1) Should the compiler complain? I don't have much experience with
    using the 'pointer to data member' stuff, but based on the research I've
    just done on the net, the code seems reasonable.

    (2) If I move the call from the initializer list to the ctor body by
    commenting out line (A) and uncommenting line (B), the compiler error
    becomes:

    test2.cpp: In constructor `bar::bar(int foo::*)':
    test2.cpp:8: syntax error before `;' token
    test2.cpp:8: declaration of `dataMember' shadows a parameter
    test2.cpp:8: syntax error before `;' token

    So, it seems the original problem persists which is reasonable but now
    there's this additional shadowing issue. It's not clear to me what
    parameer 'dataMember' is shadowing here? If anyone could explain this
    to me it would be great.

    Thanks in advance for any feedback!

    -exits
    Exits Funnel, Jan 8, 2005
    #1
    1. Advertising

  2. "Exits Funnel" <> wrote...
    > Consider this code which is a very trimmed down version of some I've
    > inherited and am trying to port from windows to g++:
    >
    > //Begin test1.cpp
    > class foo { int i; int j; };
    >
    > class bar
    > {
    > bar (int foo::* dataMember)
    > :eek:ffsetof (foo, *dataMember) //Call this Line (A)
    > {
    > // int i = offsetof (foo, *dataMember); //Call this Line (B)
    > }
    > };
    > //End test1.cpp
    >
    > when I try to compile test1.cpp with g++, the compiler has this to say:
    >
    > test2.cpp: In constructor `bar::bar(int foo::*)':
    > test2.cpp:6: syntax error before `;' token
    >
    > A couple of questions then:
    >
    > (1) Should the compiler complain? I don't have much experience with using
    > the 'pointer to data member' stuff, but based on the research I've just
    > done on the net, the code seems reasonable.
    >
    > (2) If I move the call from the initializer list to the ctor body by
    > commenting out line (A) and uncommenting line (B), the compiler error
    > becomes:
    >
    > test2.cpp: In constructor `bar::bar(int foo::*)':
    > test2.cpp:8: syntax error before `;' token
    > test2.cpp:8: declaration of `dataMember' shadows a parameter
    > test2.cpp:8: syntax error before `;' token
    >
    > So, it seems the original problem persists which is reasonable but now
    > there's this additional shadowing issue. It's not clear to me what
    > parameer 'dataMember' is shadowing here? If anyone could explain this to
    > me it would be great.


    'offsetof' is reserved and defined only when used with POD. Your class
    is not POD, so using 'offsetof' with it is essentially prohibited.

    Use pointers to members, if you have to, but you'll probably be better off
    if you rewrite the algorithm that was written to require 'offsetof'.

    As to your particular code, 'offsetof' is a macro that usually expands into
    a constant integral expression. What is the constant integral expression
    doing in the initialiser list of that constructor? It's like writing

    class bar {
    bar(int blah) : 42 {}
    };

    What's the "42" for? What are you trying to do with it?

    Victor
    Victor Bazarov, Jan 8, 2005
    #2
    1. Advertising

  3. Exits Funnel

    Jerry Coffin Guest

    > 'offsetof' is reserved and defined only when used with POD. Your
    class
    > is not POD, so using 'offsetof' with it is essentially prohibited.


    That was my first reaction too, but it's incorrect. He's calling
    offsetof _in_ the ctor of bar (and having an explicit ctor means bar
    isn't a POD type), but the argument he's passing is foo -- and foo IS a
    POD type.

    The problem is that he's passing a _pointer_ to a member where offsetof
    expects the _name_ of the member. In C++, offsetof is really more
    tolerated than fully supported -- it doesn't work with new-fangled
    things like pointers to members.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Jan 8, 2005
    #3
  4. Exits Funnel

    Exits Funnel Guest

    Thanks for taking the time to reply, Victor.

    > 'offsetof' is reserved and defined only when used with POD. Your class
    > is not POD, so using 'offsetof' with it is essentially prohibited.


    This is good to know; I couldn't find much info on offsetof anywhere.
    It's not clear to me though what makes foo not a POD. Is it just that
    the members are private? I just modified the code to make them public
    but I get the same error.

    >
    > Use pointers to members, if you have to, but you'll probably be better off
    > if you rewrite the algorithm that was written to require 'offsetof'.


    Hopefully, I'll be able to go this route but it's ALOT of code and I'd
    like to get it running sooner rather than later.

    >
    > As to your particular code, 'offsetof' is a macro that usually expands into
    > a constant integral expression. What is the constant integral expression
    > doing in the initialiser list of that constructor?


    Good point. Actually, I always try to trim as much of the code away as
    possible while still retaining the error before posting to USENET.
    Maybe I went a bit too far this time :) The actual code was, of course,
    something like this:

    bar (int foo::* dataMember)
    :myVal (offsetof (foo, *dataMember)) //Call this Line (A)

    -exits

    >
    Exits Funnel, Jan 8, 2005
    #4
  5. "Jerry Coffin" <> wrote...
    >> 'offsetof' is reserved and defined only when used with POD. Your

    > class
    >> is not POD, so using 'offsetof' with it is essentially prohibited.

    >
    > That was my first reaction too, but it's incorrect. He's calling
    > offsetof _in_ the ctor of bar (and having an explicit ctor means bar
    > isn't a POD type), but the argument he's passing is foo -- and foo IS a
    > POD type.


    How is it POD if it's a class and the members are private?

    V
    Victor Bazarov, Jan 8, 2005
    #5
  6. "Exits Funnel" <> wrote...
    > [...] Actually, I always try to trim as much of the code away as possible
    > while still retaining the error before posting to USENET. Maybe I went a
    > bit too far this time :) The actual code was, of course, something like
    > this:
    >
    > bar (int foo::* dataMember)
    > :myVal (offsetof (foo, *dataMember)) //Call this Line (A)


    Well, a pointer to member cannot be used without the object.
    The expression (*blah) where 'blah' is a pointer to member is
    meaningless in C++.

    V
    Victor Bazarov, Jan 8, 2005
    #6
  7. Exits Funnel

    Jack Klein Guest

    On Sat, 08 Jan 2005 12:06:24 -0500, Exits Funnel
    <> wrote in comp.lang.c++:

    > Consider this code which is a very trimmed down version of some I've
    > inherited and am trying to port from windows to g++:
    >
    > //Begin test1.cpp
    > class foo { int i; int j; };
    >
    > class bar
    > {
    > bar (int foo::* dataMember)
    > :eek:ffsetof (foo, *dataMember) //Call this Line (A)
    > {
    > // int i = offsetof (foo, *dataMember); //Call this Line (B)
    > }
    > };
    > //End test1.cpp
    >
    > when I try to compile test1.cpp with g++, the compiler has this to say:
    >
    > test2.cpp: In constructor `bar::bar(int foo::*)':
    > test2.cpp:6: syntax error before `;' token
    >
    > A couple of questions then:
    >
    > (1) Should the compiler complain? I don't have much experience with
    > using the 'pointer to data member' stuff, but based on the research I've
    > just done on the net, the code seems reasonable.
    >
    > (2) If I move the call from the initializer list to the ctor body by
    > commenting out line (A) and uncommenting line (B), the compiler error
    > becomes:
    >
    > test2.cpp: In constructor `bar::bar(int foo::*)':
    > test2.cpp:8: syntax error before `;' token
    > test2.cpp:8: declaration of `dataMember' shadows a parameter
    > test2.cpp:8: syntax error before `;' token
    >
    > So, it seems the original problem persists which is reasonable but now
    > there's this additional shadowing issue. It's not clear to me what
    > parameer 'dataMember' is shadowing here? If anyone could explain this
    > to me it would be great.
    >
    > Thanks in advance for any feedback!
    >
    > -exits


    offsetof, defined in <stdlib.h> and <cstdlib>, is a macro, not a
    function. It does not work on objects at all, but on compile-time
    symbols.

    The offsetof() macro requires two arguments, the NAME of a structure
    (or in C++, POD class) type, and the NAME of a member of that
    structure or class. The macro generates, _at compile time_ a value of
    type size_t that represents the difference in bytes between the
    address of any valid object of that type, and the address of the
    specified member within that object.

    It is evaluated completely at compile time based on names, never at
    run time and can never involve a pointer. The concept of pointers,
    let alone dereferencing pointers, does not exist at the early phase of
    compilation where macros are expanded.

    --
    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.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Jan 9, 2005
    #7
  8. Exits Funnel

    David Harmon Guest

    On Sat, 08 Jan 2005 16:21:52 -0500 in comp.lang.c++, Exits Funnel
    <> wrote,
    >It's not clear to me though what makes foo not a POD. Is it just that
    >the members are private? I just modified the code to make them public
    >but I get the same error.


    In your stripped example, it is just the private members, but I
    guess there may be a lot of other things in the real code.

    Plain Old Data is any built in or user-defined type that has:

    - no user-defined constructor
    - no user-defined copy assignment operator
    - no user defined destructor
    - no virtual functions
    - no base class (i.e. it is not a derived class)
    - no private or protected non-static data members
    - no non-static members of type pointer to member
    - no non-static members that are references
    - no non-static data members that are not also POD types

    But that has little to do with the current problem.

    >Good point. Actually, I always try to trim as much of the code away as
    >possible while still retaining the error before posting to USENET.
    >Maybe I went a bit too far this time :) The actual code was, of course,
    > something like this:
    >
    > bar (int foo::* dataMember)
    > :myVal (offsetof (foo, *dataMember)) //Call this Line (A)


    Different compilers can be expected to implement 'offsetof' in
    slightly different ways, to match their differing object model.
    Here is an example of a definition of 'offsetof' ripped from a
    compiler that I happened to have handy:

    #define offsetof(t,i) ((size_t)((char *)&((t *)0)->i - (char *)0))

    You notice the second parameter appears in the context '->i'. When
    you substitute the macro argument, you get '->*datamember', invoking
    the ->* operator almost by accident and luck. If the macro had been
    written with '-> i' it would still work with a member name, but not
    the pointer.

    If foo is a POD your luck may hold. If the *datamember pointer
    involves any of the magic that is needed to implement member
    pointers when an inheritance hierarchy is involved, etc., then it
    becomes less likely that '(t *)0' will slide to success.

    Either way, '*datamember' is not what 'offsetof' was designed to
    support.
    David Harmon, Jan 9, 2005
    #8
  9. Exits Funnel

    Jerry Coffin Guest

    > This is good to know; I couldn't find much info on offsetof anywhere.

    > It's not clear to me though what makes foo not a POD. Is it just that


    > the members are private? I just modified the code to make them public


    > but I get the same error.


    Being private _does_ keep them from being POD (I'm not sure what I was
    thinking when I said otherwise) but my original point about the problem
    remains -- the real problem is that you're supplying a pointer to a
    member but it needs the name of a member instead. The bottom line is
    that this technique simply can't work, whether it's applied to a POD
    type or not.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Jan 9, 2005
    #9
  10. Exits Funnel

    Exits Funnel Guest

    David, thanks for taking the time to reply.

    > #define offsetof(t,i) ((size_t)((char *)&((t *)0)->i - (char *)0))


    In which header did you find this? It's not clear to me what the point
    of the ' - (char *)0' bit is. The only macro definition I could find on
    my platform (RedHat Linux) was in stddef.h and looked like this:

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

    Actually, I wasn't #including stddef.h which is obviously part of my
    problem. I thought that offsetof( ) was a built in part of the language
    similar to sizeof. Would one expect to have to explicitly include some
    header file to use offsetof?

    > You notice the second parameter appears in the context '->i'. When
    > you substitute the macro argument, you get '->*datamember', invoking
    > the ->* operator almost by accident and luck. If the macro had been
    > written with '-> i' it would still work with a member name, but not
    > the pointer.
    >
    > If foo is a POD your luck may hold. If the *datamember pointer
    > involves any of the magic that is needed to implement member
    > pointers when an inheritance hierarchy is involved, etc., then it
    > becomes less likely that '(t *)0' will slide to success.
    >
    > Either way, '*datamember' is not what 'offsetof' was designed to
    > support.
    >


    This is all very helpful information, thanks again.

    -exits
    Exits Funnel, Jan 9, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hiroki Horiuchi

    g++ "offsetof" problem

    Hiroki Horiuchi, Nov 25, 2003, in forum: C++
    Replies:
    5
    Views:
    6,560
    red floyd
    Nov 25, 2003
  2. Tony Johansson

    offsetof

    Tony Johansson, Dec 16, 2004, in forum: C++
    Replies:
    1
    Views:
    446
    Alf P. Steinbach
    Dec 16, 2004
  3. Tony Johansson

    More offsetof

    Tony Johansson, Dec 16, 2004, in forum: C++
    Replies:
    3
    Views:
    507
    Mike Wahler
    Dec 18, 2004
  4. Alejo

    offsetof

    Alejo, Jul 15, 2003, in forum: C Programming
    Replies:
    20
    Views:
    1,048
    Dan Pop
    Jul 22, 2003
  5. Arthur J. O'Dwyer

    Pre-offsetof() question

    Arthur J. O'Dwyer, Oct 6, 2003, in forum: C Programming
    Replies:
    6
    Views:
    400
    Arthur J. O'Dwyer
    Oct 7, 2003
Loading...

Share This Page