Valid C++?

Discussion in 'C++' started by andrew queisser, Jun 6, 2006.

  1. Is this code below valid C++? I'd like to use this construct but I'm not
    sure if it'll be portable.

    struct foo
    {
    char x[128];
    };
    struct bar
    {
    char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
    };



    Thanks,
    Andrew
    andrew queisser, Jun 6, 2006
    #1
    1. Advertising

  2. andrew queisser

    Noah Roberts Guest

    andrew queisser wrote:
    > Is this code below valid C++? I'd like to use this construct but I'm not
    > sure if it'll be portable.
    >
    > struct foo
    > {
    > char x[128];
    > };
    > struct bar
    > {
    > char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
    > };


    Yes it is valid. However, I believe it also results in undefined
    behavior.

    On the other hand, it is a common technique to use especially in C, for
    instance:

    diff = (&((foo*)0)->x - ((foo*)0))

    or something similar.

    Most compilers create code that does what you expect here. Since you
    are not reading from x or writing to it its just arith operations on a
    pointer variable.
    Noah Roberts, Jun 6, 2006
    #2
    1. Advertising

  3. andrew queisser

    mlimber Guest

    andrew queisser wrote:
    > Is this code below valid C++? I'd like to use this construct but I'm not
    > sure if it'll be portable.
    >
    > struct foo
    > {
    > char x[128];
    > };
    > struct bar
    > {
    > char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
    > };


    Though that seems to work, for the sake of clarity, I would do it
    differently. At worst, something like this:

    char sameSizeAsFooX[ sizeof foo().x ];

    Better, IMHO, would be:

    struct foo
    {
    enum { SIZE = 128 };
    char x[SIZE];
    };

    struct bar
    {
    char sameSizeAsFooX[ foo::SIZE ];
    };

    Cheers! --M
    mlimber, Jun 6, 2006
    #3
  4. andrew queisser wrote:
    > Is this code below valid C++? I'd like to use this construct but I'm
    > not sure if it'll be portable.
    >
    > struct foo
    > {
    > char x[128];
    > };
    > struct bar
    > {
    > char sameSizeAsFooX[ sizeof ((foo *)0)->x ];


    It is OK, I guess. Seems rather dangerous though, like dereferencing
    a null pointer. Perhaps it would be less scary to do

    char sameSizeAsFoox[ sizeof foo().x ];

    (although it does require for 'foo' to be default-constructible while
    your solution does not).

    > };


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jun 6, 2006
    #4
  5. Noah Roberts wrote:
    > andrew queisser wrote:
    >> Is this code below valid C++? I'd like to use this construct but I'm
    >> not sure if it'll be portable.
    >>
    >> struct foo
    >> {
    >> char x[128];
    >> };
    >> struct bar
    >> {
    >> char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
    >> };

    >
    > Yes it is valid. However, I believe it also results in undefined
    > behavior.


    It does not. The dereferencing behind the -> is never evaluated.

    > [..]


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jun 6, 2006
    #5
  6. mlimber wrote:
    > andrew queisser wrote:
    >> Is this code below valid C++? I'd like to use this construct but I'm
    >> not sure if it'll be portable.
    >>
    >> struct foo
    >> {
    >> char x[128];
    >> };
    >> struct bar
    >> {
    >> char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
    >> };

    >
    > Though that seems to work, for the sake of clarity, I would do it
    > differently. At worst, something like this:
    >
    > char sameSizeAsFooX[ sizeof foo().x ];


    This requires 'foo' to be default-constructible, which is not always
    possible.

    > Better, IMHO, would be:
    >
    > struct foo
    > {
    > enum { SIZE = 128 };
    > char x[SIZE];
    > };
    >
    > struct bar
    > {
    > char sameSizeAsFooX[ foo::SIZE ];
    > };


    I agree. The problem is that editing 'foo' to introduce 'SIZE' is not
    always possible. Besides, the trick with (0)-> can be used in templates
    whereas you cannot expect every class that has 'x' member for which you
    want to create a corresponding 'sameSizeAs..' also contains 'SIZE'...

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jun 6, 2006
    #6
  7. * Victor Bazarov:
    > andrew queisser wrote:
    >> Is this code below valid C++? I'd like to use this construct but I'm
    >> not sure if it'll be portable.
    >>
    >> struct foo
    >> {
    >> char x[128];
    >> };
    >> struct bar
    >> {
    >> char sameSizeAsFooX[ sizeof ((foo *)0)->x ];

    >
    > It is OK, I guess. Seems rather dangerous though, like dereferencing
    > a null pointer. Perhaps it would be less scary to do
    >
    > char sameSizeAsFoox[ sizeof foo().x ];
    >
    > (although it does require for 'foo' to be default-constructible while
    > your solution does not).
    >
    >> };


    On the one hand, dereferencing a null-pointer is formally UB no matter
    which context (except in a typeid expression).

    On the other hand, the only harm it can do inside a sizeof is to make
    som rather dumb compiler choke on the expression, and it's an old idiom.

    On the third & gripping hand, at the technical level, where we don't
    care about how a better design might make the need go away, this is
    really a job for the Unimplemented Fake Function, the UFF,

    foo& foon();

    char samesizeAsFoox[ sizeof( foon().x ) ];


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jun 6, 2006
    #7
  8. andrew queisser

    Noah Roberts Guest

    Alf P. Steinbach wrote:

    > On the third & gripping hand, at the technical level, where we don't
    > care about how a better design might make the need go away, this is
    > really a job for the Unimplemented Fake Function, the UFF,
    >
    > foo& foon();
    >
    > char samesizeAsFoox[ sizeof( foon().x ) ];


    Heh, cute. Never seen that done before.

    Does that remove UB?
    Noah Roberts, Jun 6, 2006
    #8
  9. Alf P. Steinbach wrote:
    > * Victor Bazarov:
    >> andrew queisser wrote:
    >>> Is this code below valid C++? I'd like to use this construct but I'm
    >>> not sure if it'll be portable.
    >>>
    >>> struct foo
    >>> {
    >>> char x[128];
    >>> };
    >>> struct bar
    >>> {
    >>> char sameSizeAsFooX[ sizeof ((foo *)0)->x ];

    >>
    >> It is OK, I guess. Seems rather dangerous though, like dereferencing
    >> a null pointer. Perhaps it would be less scary to do
    >>
    >> char sameSizeAsFoox[ sizeof foo().x ];
    >>
    >> (although it does require for 'foo' to be default-constructible while
    >> your solution does not).
    >>
    >>> };

    >
    > On the one hand, dereferencing a null-pointer is formally UB no matter
    > which context (except in a typeid expression).


    According to 3.2/2 the full expression ((foo*)0)->x is not evaluated.
    'sizeof' has the same standing as 'typeid' in this matter, AFAICT.

    > [..a nice trick with UFF redacted..]


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jun 6, 2006
    #9
  10. andrew queisser

    Rolf Magnus Guest

    Alf P. Steinbach wrote:

    > * Victor Bazarov:
    >> andrew queisser wrote:
    >>> Is this code below valid C++? I'd like to use this construct but I'm
    >>> not sure if it'll be portable.
    >>>
    >>> struct foo
    >>> {
    >>> char x[128];
    >>> };
    >>> struct bar
    >>> {
    >>> char sameSizeAsFooX[ sizeof ((foo *)0)->x ];

    >>
    >> It is OK, I guess. Seems rather dangerous though, like dereferencing
    >> a null pointer. Perhaps it would be less scary to do
    >>
    >> char sameSizeAsFoox[ sizeof foo().x ];
    >>
    >> (although it does require for 'foo' to be default-constructible while
    >> your solution does not).
    >>
    >>> };

    >
    > On the one hand, dereferencing a null-pointer is formally UB no matter
    > which context (except in a typeid expression).


    Actually, the exception covers not only typeid, but also sizeof:

    "An expression is potentially evaluated unless either it is the operand of
    the sizeof operator (5.3.3), or it is the operand of the typeid operator
    and does not designate an lvalue of polymorphic class type (5.2.8)."
    Rolf Magnus, Jun 6, 2006
    #10
  11. Noah Roberts wrote:
    > Alf P. Steinbach wrote:
    >
    >> On the third & gripping hand, at the technical level, where we don't
    >> care about how a better design might make the need go away, this is
    >> really a job for the Unimplemented Fake Function, the UFF,
    >>
    >> foo& foon();
    >>
    >> char samesizeAsFoox[ sizeof( foon().x ) ];

    >
    > Heh, cute. Never seen that done before.
    >
    > Does that remove UB?


    It cannot remove what does not exist. Further, it creates a violation
    of the ODR, if 'sizeof' expression *were* evaluated. If 'sizeof' is not
    evaluated (and it isn't, see 3.2/2), then neither is a violation.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jun 6, 2006
    #11
  12. andrew queisser

    Noah Roberts Guest

    Noah Roberts wrote:
    > Alf P. Steinbach wrote:
    >
    > > On the third & gripping hand, at the technical level, where we don't
    > > care about how a better design might make the need go away, this is
    > > really a job for the Unimplemented Fake Function, the UFF,
    > >
    > > foo& foon();
    > >
    > > char samesizeAsFoox[ sizeof( foon().x ) ];

    >
    > Heh, cute. Never seen that done before.


    This doesn't work if you're trying to implement an offset function.
    Noah Roberts, Jun 6, 2006
    #12
  13. andrew queisser schrieb:
    > Is this code below valid C++? I'd like to use this construct but I'm not
    > sure if it'll be portable.
    >
    > struct foo
    > {
    > char x[128];
    > };
    > struct bar
    > {
    > char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
    > };
    >
    >
    >
    > Thanks,
    > Andrew
    >
    >


    struct foo {
    char x[128];
    };

    union bar {
    struct foo dummy;
    char * sameSizeAsFoo;
    };

    maybe that helps

    Regards, Daniel
    =?ISO-8859-1?Q?Sch=FCle_Daniel?=, Jun 6, 2006
    #13
  14. Noah Roberts wrote:
    > Noah Roberts wrote:
    >> Alf P. Steinbach wrote:
    >>
    >>> On the third & gripping hand, at the technical level, where we don't
    >>> care about how a better design might make the need go away, this is
    >>> really a job for the Unimplemented Fake Function, the UFF,
    >>>
    >>> foo& foon();
    >>>
    >>> char samesizeAsFoox[ sizeof( foon().x ) ];

    >>
    >> Heh, cute. Never seen that done before.

    >
    > This doesn't work if you're trying to implement an offset function.


    What's "an offset function"?

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jun 6, 2006
    #14
  15. andrew queisser

    Noah Roberts Guest

    Victor Bazarov wrote:
    > Noah Roberts wrote:
    > > Noah Roberts wrote:
    > >> Alf P. Steinbach wrote:
    > >>
    > >>> On the third & gripping hand, at the technical level, where we don't
    > >>> care about how a better design might make the need go away, this is
    > >>> really a job for the Unimplemented Fake Function, the UFF,
    > >>>
    > >>> foo& foon();
    > >>>
    > >>> char samesizeAsFoox[ sizeof( foon().x ) ];
    > >>
    > >> Heh, cute. Never seen that done before.

    > >
    > > This doesn't work if you're trying to implement an offset function.

    >
    > What's "an offset function"?


    A function that calculates the offset of a member of course.
    Noah Roberts, Jun 6, 2006
    #15
  16. andrew queisser

    Andre Kostur Guest

    On Tue, 06 Jun 2006 12:11:14 -0700, Noah Roberts wrote:

    > Victor Bazarov wrote:
    >> Noah Roberts wrote:
    >> > Noah Roberts wrote:
    >> >> Alf P. Steinbach wrote:
    >> >>
    >> >>> On the third & gripping hand, at the technical level, where we don't
    >> >>> care about how a better design might make the need go away, this is
    >> >>> really a job for the Unimplemented Fake Function, the UFF,
    >> >>>
    >> >>> foo& foon();
    >> >>>
    >> >>> char samesizeAsFoox[ sizeof( foon().x ) ];
    >> >>
    >> >> Heh, cute. Never seen that done before.
    >> >
    >> > This doesn't work if you're trying to implement an offset function.

    >>
    >> What's "an offset function"?

    >
    > A function that calculates the offset of a member of course.


    Like offsetof() ?
    Andre Kostur, Jun 6, 2006
    #16
  17. Noah Roberts wrote:
    > Victor Bazarov wrote:
    >> Noah Roberts wrote:
    >>> Noah Roberts wrote:
    >>>> Alf P. Steinbach wrote:
    >>>>
    >>>>> On the third & gripping hand, at the technical level, where we
    >>>>> don't care about how a better design might make the need go away,
    >>>>> this is really a job for the Unimplemented Fake Function, the UFF,
    >>>>>
    >>>>> foo& foon();
    >>>>>
    >>>>> char samesizeAsFoox[ sizeof( foon().x ) ];
    >>>>
    >>>> Heh, cute. Never seen that done before.
    >>>
    >>> This doesn't work if you're trying to implement an offset function.

    >>
    >> What's "an offset function"?

    >
    > A function that calculates the offset of a member of course.


    Ah... OK. What would be the purpose of it? I don't think I ever had
    a need in a function like that, and that's why I'm asking. Thanks!

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jun 6, 2006
    #17
  18. * Rolf Magnus:
    > Alf P. Steinbach wrote:
    >
    >> * Victor Bazarov:
    >>> andrew queisser wrote:
    >>>> Is this code below valid C++? I'd like to use this construct but I'm
    >>>> not sure if it'll be portable.
    >>>>
    >>>> struct foo
    >>>> {
    >>>> char x[128];
    >>>> };
    >>>> struct bar
    >>>> {
    >>>> char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
    >>> It is OK, I guess. Seems rather dangerous though, like dereferencing
    >>> a null pointer. Perhaps it would be less scary to do
    >>>
    >>> char sameSizeAsFoox[ sizeof foo().x ];
    >>>
    >>> (although it does require for 'foo' to be default-constructible while
    >>> your solution does not).
    >>>
    >>>> };

    >> On the one hand, dereferencing a null-pointer is formally UB no matter
    >> which context (except in a typeid expression).

    >
    > Actually, the exception covers not only typeid, but also sizeof:
    >
    > "An expression is potentially evaluated unless either it is the operand of
    > the sizeof operator (5.3.3), or it is the operand of the typeid operator
    > and does not designate an lvalue of polymorphic class type (5.2.8)."


    No, that isn't the exception that applies to typeid.

    And no, it doesn't matter whether a dereferencing is potentially
    evaluated or not.


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jun 6, 2006
    #18
  19. andrew queisser

    Noah Roberts Guest

    Andre Kostur wrote:
    > On Tue, 06 Jun 2006 12:11:14 -0700, Noah Roberts wrote:


    > > A function that calculates the offset of a member of course.

    >
    > Like offsetof() ?


    yes, exactly like that.

    usual definition something like so:

    #define offsetof(s,m) (size_t)&(((s *)0)->m)

    As to the question of usefulness - not very. Not in C++ anyway.
    Noah Roberts, Jun 6, 2006
    #19
  20. andrew queisser

    Bo Persson Guest

    "Noah Roberts" <> skrev i meddelandet
    news:...
    >
    > Andre Kostur wrote:
    >> On Tue, 06 Jun 2006 12:11:14 -0700, Noah Roberts wrote:

    >
    >> > A function that calculates the offset of a member of course.

    >>
    >> Like offsetof() ?

    >
    > yes, exactly like that.
    >
    > usual definition something like so:
    >
    > #define offsetof(s,m) (size_t)&(((s *)0)->m)
    >
    > As to the question of usefulness - not very. Not in C++ anyway.
    >


    And that isn't really valid C++ anyway.

    It is only *if* the compiler implementor cares to define the behavior
    for the offsetof macro, that this works. Otherwise not.

    An equally common definition is

    #define offsetof(_Structure, _Member)
    __builtin_offsetof(_Structure, _Member)

    where the compiler people (gcc) have chosen to support another trick.


    Bo Persson
    Bo Persson, Jun 6, 2006
    #20
    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. Aschel Kritsos

    Valid file types

    Aschel Kritsos, Nov 11, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    591
  2. Ajit
    Replies:
    1
    Views:
    3,599
    Victor Garcia Aprea [MVP]
    Apr 24, 2004
  3. CT

    vbc is not valid command

    CT, Oct 30, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    2,833
  4. Pial
    Replies:
    6
    Views:
    52,394
    Nassos
    Apr 28, 2005
  5. MM
    Replies:
    3
    Views:
    443
    Kai Harrekilde-Petersen
    Jun 19, 2004
Loading...

Share This Page