Operand of postfix operator ->

Discussion in 'C Programming' started by Rajesh S R, Apr 24, 2007.

  1. Rajesh S R

    Rajesh S R Guest

    Consider the following code:
    int main()
    {
    struct name
    {
    long a;
    int b;
    long c;
    }s={3,4,5},*p;
    p=&s;

    printf("%d",*(int *)((char *)p+(unsigned int)&(((struct name*)0)-
    >b)));


    return 0;
    }

    Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    C99?

    That is,
    Can an operand of postfix operator -> be a null pointer?

    Please clarify.

    Thanks in advance for the reply.
     
    Rajesh S R, Apr 24, 2007
    #1
    1. Advertising

  2. In article <>,
    Rajesh S R <> wrote:

    >Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    >C99?


    No.

    >That is,
    >Can an operand of postfix operator -> be a null pointer?


    -> is not a postfix operator. It has two operands and appears between
    them, so it's an infix operator.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, Apr 24, 2007
    #2
    1. Advertising

  3. Rajesh S R

    Chris Dollin Guest

    Rajesh S R wrote:

    > Consider the following code:
    > int main()
    > {
    > struct name
    > {
    > long a;
    > int b;
    > long c;
    > }s={3,4,5},*p;
    > p=&s;


    Were we pairing, I'd not let that stay like that. Oh no.

    > printf("%d",*(int *)((char *)p+(unsigned int)&(((struct name*)0)-
    >>b)));


    At this point I'd ask you what on earth you were trying to do.
    I wouldn't much care whether it was legal-by-the-Standard; I'd
    care that it was indecently obscure.

    > return 0;
    > }
    >
    > Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    > C99?


    I don't think so.

    > That is,
    > Can an operand of postfix operator -> be a null pointer?


    Yes, it can be. The result is undefined. So don't do that.

    (Your clarification asks a different question from your original.)

    --
    Nit-picking is best done among friends.

    Hewlett-Packard Limited registered office: Cain Road, Bracknell,
    registered no: 690597 England Berks RG12 1HN
     
    Chris Dollin, Apr 24, 2007
    #3
  4. In article <f0kv5l$isv$>,
    Chris Dollin <> wrote:

    >> printf("%d",*(int *)((char *)p+(unsigned int)&(((struct name*)0)-
    >>>b)));


    >At this point I'd ask you what on earth you were trying to do.


    Presumably he's trying to implement sizeof(), as apparently everyone
    in India is doing these days. I assume he's on the same course as all
    the others asking similar questions.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, Apr 24, 2007
    #4
  5. "Rajesh S R" <> wrote in message
    news:...
    > printf("%d",*(int *)((char *)p+(unsigned int)&(((struct name*)0)-
    >>b)));

    ....
    > Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    > C99?


    No. What you're seeing is one rather common implementation of offsetof(),
    but it's officially UB for _you_ to use this construct unless you're writing
    the implementation itself. Use offsetof() and you don't have to worry about
    those systems where it doesn't actually work.

    > That is,
    > Can an operand of postfix operator -> be a null pointer?


    It's an infix operator, and the first operand must be a pointer to an
    object. Since a null pointer constant does not point to an object by
    definition, it's UB.

    S

    --
    Stephen Sprunk "Those people who think they know everything
    CCIE #3723 are a great annoyance to those of us who do."
    K5SSS --Isaac Asimov


    --
    Posted via a free Usenet account from http://www.teranews.com
     
    Stephen Sprunk, Apr 24, 2007
    #5
  6. Rajesh S R

    Rajesh S R Guest

    Thanks for ur reply.

    > -> is not a postfix operator. It has two operands and appears between
    > them, so it's an infix operator.


    But C standards categorises an -> as postfix operator( C99 6.5.2 ) .
    So what's wrong in stating it as a postfix operator?
    Even C99 calls it that way!
     
    Rajesh S R, Apr 24, 2007
    #6
  7. In article <>,
    Rajesh S R <> wrote:

    >> -> is not a postfix operator. It has two operands and appears between
    >> them, so it's an infix operator.


    >But C standards categorises an -> as postfix operator( C99 6.5.2 ) .


    You're right.

    I can't imagine why they decided to misuse a well-defined term in that
    way.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, Apr 24, 2007
    #7
  8. Rajesh S R

    Rajesh S R Guest

    Thanks for your reply.

    > -> is not a postfix operator. It has two operands and appears between
    > them, so it's an infix operator.


    (C99 6.5.2) categorises -> as postfix operator. So whats wrong in
    calling it that way?
     
    Rajesh S R, Apr 24, 2007
    #8
  9. Rajesh S R wrote:
    > Consider the following code:
    > int main()
    > {
    > struct name
    > {
    > long a;
    > int b;
    > long c;
    > }s={3,4,5},*p;
    > p=&s;
    >
    > printf("%d",*(int *)((char *)p+(unsigned int)&(((struct name*)0)-
    >> b)));

    >
    > return 0;
    > }
    >
    > Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    > C99?


    There are otherwise enough errors in your code to make "valid as per
    C99" a sick joke. And this is the most perverse way I have ever seen of
    spelling the expression "p->b".

    > That is,
    > Can an operand of postfix operator -> be a null pointer?

    -> is not a postfix operator. Strangely, your code claims it isn't a
    token at all.
     
    Martin Ambuhl, Apr 24, 2007
    #9
  10. Rajesh S R

    Army1987 Guest

    "Rajesh S R" <> ha scritto nel messaggio
    news:...
    > Consider the following code:
    > int main()
    > {
    > struct name
    > {
    > long a;
    > int b;
    > long c;
    > }s={3,4,5},*p;
    > p=&s;
    >
    > printf("%d",*(int *)((char *)p+(unsigned int)&(((struct name*)0)-
    >>b)));

    You've managed to beat my lecturer (and the book he copied from) in the
    contest of the ugliest line of code ever:
    http://groups.google.com/group/comp.lang.c/msg/f0495c8e34d3016?as_umsgid=evt7mc$d5o$

    > return 0;
    > }
    >
    > Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    > C99?

    What the hell are you trying to do?
     
    Army1987, Apr 24, 2007
    #10
  11. (Richard Tobin) writes:
    > In article <>,
    > Rajesh S R <> wrote:
    >
    >>> -> is not a postfix operator. It has two operands and appears between
    >>> them, so it's an infix operator.

    >
    >>But C standards categorises an -> as postfix operator( C99 6.5.2 ) .

    >
    > You're right.
    >
    > I can't imagine why they decided to misuse a well-defined term in that
    > way.


    Probably because the thing on the right hand side isn't really an
    operand; it must be the name of a member of the appropriate structure
    or union. In s->m, s must be an expression (specifically a
    postfix-expression), but m *cannot* be an expression.

    The way I sometimes think of it (which is not the way the standard
    expresses it) is that a declaration like:

    struct foo { int x; int y; };

    implicitly creates *four* postfix operators: ".x" and ".y", which can
    be applied to expresions of type struct foo, and "->x" and "->y",
    which can be applied to expressions of type struct foo*.

    --
    Keith Thompson (The_Other_Keith) <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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 24, 2007
    #11
  12. In article <>,
    Keith Thompson <> wrote:

    >> I can't imagine why they decided to misuse a well-defined term in that
    >> way.


    >Probably because the thing on the right hand side isn't really an
    >operand; it must be the name of a member of the appropriate structure
    >or union. In s->m, s must be an expression (specifically a
    >postfix-expression), but m *cannot* be an expression.


    This argument would be a lot more plausible if they didn't also call
    the array subscripting operator postfix. It's particular egregious in
    that case as the subscripting operator is commutative!

    I suppose they just considered that these operators are "accessors",
    where the "main" operand is (usually) on the right.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, Apr 24, 2007
    #12
  13. Rajesh S R

    whyglinux Guest

    Rajesh S R <> wrote:

    >
    > Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    > C99?
    >
    > That is,
    > Can an operand of postfix operator -> be a null pointer?


    Yes, the expression is defined and the left operand of -> can be a
    null pointer.

    We all know that dereferencing a null pointer produces undefined
    behavior, but if the -> operator is not evaluated, it will not.

    One such example with defined behavior is: sizeof( ((struct name*)0)-
    >b ), another is your expression.


    There exists a special rule in C99:

    "If the operand (of the unary & operator) is the result of a unary *
    operator, neither that operator nor the & operator is evaluated and
    the result is as if both were omitted"

    The expression &(((struct name*)0)->b) can be re-written as
    &((*((struct name*)0)).b) and thus the above rule can be applied -
    neither the & nor the * operator will be evaluated. No evaluation then
    means no undefined behavior.
     
    whyglinux, Apr 25, 2007
    #13
  14. Rajesh S R

    Flash Gordon Guest

    whyglinux wrote, On 25/04/07 05:55:
    > Rajesh S R <> wrote:
    >
    >> Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    >> C99?
    >>
    >> That is,
    >> Can an operand of postfix operator -> be a null pointer?

    >
    > Yes, the expression is defined and the left operand of -> can be a
    > null pointer.
    >
    > We all know that dereferencing a null pointer produces undefined
    > behavior, but if the -> operator is not evaluated, it will not.


    I disagree, see below.

    > One such example with defined behavior is: sizeof( ((struct name*)0)-
    >> b ), another is your expression.

    >
    > There exists a special rule in C99:
    >
    > "If the operand (of the unary & operator) is the result of a unary *
    > operator, neither that operator nor the & operator is evaluated and
    > the result is as if both were omitted"
    >
    > The expression &(((struct name*)0)->b) can be re-written as
    > &((*((struct name*)0)).b) and thus the above rule can be applied -
    > neither the & nor the * operator will be evaluated. No evaluation then
    > means no undefined behavior.


    The operand is not the result of a unary *, it is the result of
    selecting an element of a struct *after* dereferencing the unary * to
    find the relevant instance of the struct. Therefore that exception does
    not apply.

    There is also still the question "why not use the offsetof macro? that's
    what it's there fore."
    --
    Flash Gordon
     
    Flash Gordon, Apr 25, 2007
    #14
  15. Rajesh S R

    whyglinux Guest

    Flash Gordon <> wrote:
    > whyglinux wrote, On 25/04/07 05:55:
    >
    > > Rajesh S R <> wrote:

    >
    > >> Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    > >> C99?

    >
    > >> That is,
    > >> Can an operand of postfix operator -> be a null pointer?

    >
    > > Yes, the expression is defined and the left operand of -> can be a
    > > null pointer.

    >
    > > We all know that dereferencing a null pointer produces undefined
    > > behavior, but if the -> operator is not evaluated, it will not.

    >
    > I disagree, see below.
    >
    > > One such example with defined behavior is: sizeof( ((struct name*)0)-
    > >> b ), another is your expression.

    >
    > > There exists a special rule in C99:

    >
    > > "If the operand (of the unary & operator) is the result of a unary *
    > > operator, neither that operator nor the & operator is evaluated and
    > > the result is as if both were omitted"

    >
    > > The expression &(((struct name*)0)->b) can be re-written as
    > > &((*((struct name*)0)).b) and thus the above rule can be applied -
    > > neither the & nor the * operator will be evaluated. No evaluation then
    > > means no undefined behavior.

    >
    > The operand is not the result of a unary *, it is the result of
    > selecting an element of a struct *after* dereferencing the unary * to
    > find the relevant instance of the struct. Therefore that exception does
    > not apply.
    >
    > There is also still the question "why not use the offsetof macro? that's
    > what it's there fore."
    > --
    > Flash Gordon


    Yes, you are right - the operand is not the result of the unary *
    operator and thus my cited rule can not be applied.

    As other posters have already said: the expression (unsigned
    int)&(((struct name*)0)->b) is undefined since dereferencing a null
    pointer. For the reason, we should not write suchlike code. Instead we
    should use the offsetof macro defined in <stddef.h> directly.

    Thanks.
     
    whyglinux, Apr 26, 2007
    #15
  16. Rajesh S R

    Rajesh S R Guest

    > What the hell are you trying to do?

    Nothing, This is not the code I contrived by myself!
    I saw this code in a C Quiz site.
    I suspected it to be a UB and at the same time I was not sure if it's
    really one.
    So I just want to get it confirmed before proclaiming to myself that
    it is a UB!

    I thank you all for your responses. Finally, my doubt is clear and
    now, I am sure that it is a UB.
     
    Rajesh S R, Apr 26, 2007
    #16
  17. Rajesh S R

    Rajesh S R Guest

    On Apr 24, 5:54 pm, Rajesh S R <> wrote:
    > Consider the following code:
    > int main()
    > {
    > struct name
    > {
    > long a;
    > int b;
    > long c;}s={3,4,5},*p;
    >
    > p=&s;
    >
    > printf("%d",*(int *)((char *)p+(unsigned int)&(((struct name*)0)-
    >
    > >b)));

    >
    > return 0;
    >
    > }
    >
    > Is the expression (unsigned int)&(((struct name*)0)->b) valid as per
    > C99?
    >
    > That is,
    > Can an operand of postfix operator -> be a null pointer?
    >
    > Please clarify.
    >
    > Thanks in advance for the reply.


    I thank all of you for your responses. Now a new question has popped
    out of my mind. Let me clarify that I am very much aware that my
    present question is not based on standards. Therfore one can not use
    standards to give a reply. This question is about the implementation
    and optimisation.

    My question is:
    Can the expression (unsigned int)&(((struct name*)0)->b) be evaluated
    at translation time itself, so that no ru time error is produced?

    The thing that prompted me to pose this question is that this program
    runs successfully without causing any segmentation faults in DEV-CPP
    compiler for Win-32. This makes me think that the above expression is
    evaluated at translation time itself. Please clarify.
     
    Rajesh S R, Apr 27, 2007
    #17
  18. In article <>,
    Rajesh S R <> wrote:

    >My question is:
    >Can the expression (unsigned int)&(((struct name*)0)->b) be evaluated
    >at translation time itself, so that no ru time error is produced?


    *If* the expression were legal C, then one would expect it to be a
    constant expression, just as &((&foo)->b) is when foo is a static struct
    name. It would therefore be natural for the compiler to evaluate it
    at compile time.

    It's not legal C, but it would still be natural for a compiler that
    accepted it to evaluate it at compile time.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
     
    Richard Tobin, Apr 27, 2007
    #18
  19. Rajesh S R

    Flash Gordon Guest

    Rajesh S R wrote, On 27/04/07 16:40:

    <snip>

    > out of my mind. Let me clarify that I am very much aware that my
    > present question is not based on standards. Therfore one can not use
    > standards to give a reply. This question is about the implementation
    > and optimisation.
    >
    > My question is:
    > Can the expression (unsigned int)&(((struct name*)0)->b) be evaluated
    > at translation time itself, so that no ru time error is produced?


    As it is undefined behaviour the compiler can treat it as a run time
    error, compile time error, or anything else it wants. It does not even
    have to treat it the same each time it sees it.

    > The thing that prompted me to pose this question is that this program
    > runs successfully without causing any segmentation faults in DEV-CPP
    > compiler for Win-32. This makes me think that the above expression is
    > evaluated at translation time itself. Please clarify.


    It is evaluated or not whenever the compiler or compiled program happens
    to do it.
    --
    Flash Gordon
     
    Flash Gordon, Apr 27, 2007
    #19
    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. Kim JM
    Replies:
    1
    Views:
    1,746
    Riyaz
    Apr 2, 2004
  2. Rajesh S R

    operand of postfix operator->

    Rajesh S R, Apr 24, 2007, in forum: C Programming
    Replies:
    1
    Views:
    337
    Chris Dollin
    Apr 24, 2007
  3. Replies:
    29
    Views:
    35,347
  4. , India

    postfix vs prefix operator

    , India, Jun 23, 2007, in forum: C++
    Replies:
    8
    Views:
    813
  5. Chris Forone

    postfix operator++(int) with const

    Chris Forone, Jun 20, 2008, in forum: C++
    Replies:
    7
    Views:
    1,591
    James Kanze
    Jun 20, 2008
Loading...

Share This Page