question regarding ++ operator.

Discussion in 'C Programming' started by somenath, Jan 25, 2013.

  1. somenath

    somenath Guest

    I am not able to figure out why the following progarm is not
    compiling.

    #include<stdio.h>

    int main(void)
    {
    struct test {
    int len;
    char *str;
    }*p[10];
    struct test t = { 100,"hello world" };
    struct test t1 = { 11,"HI world" };
    p[0] = &t;
    p[1] = &t1;

    printf("\n len = %d\n",(*(*(p + 1) )).len); //line 1
    printf("\n len = %d\n",(*(*++p) ).len); //line 2


    return 0;
    }
    Here p is array 10 of pointer to “struct test” and the value of p is
    &p[0]. So if p is incremented it will be pointing to the next element
    i.e p[1].
    According to me line 1 and line 2 is identical. But then why line 2 is
    not getting compiled?

    I am getting the following error
    test.c: In function `main':
    test.c:15: error: wrong type argument to increment

    My guess would be the value of p is not providing object context to +
    +.
    Is it correct?
    But then why it is not providing? Is it providing value context?
    somenath, Jan 25, 2013
    #1
    1. Advertising

  2. somenath wrote:
    > I am not able to figure out why the following progarm is not
    > compiling.
    >
    > #include<stdio.h>
    >
    > int main(void)
    > {
    > struct test {
    > int len;
    > char *str;
    > }*p[10];
    > struct test t = { 100,"hello world" };
    > struct test t1 = { 11,"HI world" };
    > p[0] =&t;
    > p[1] =&t1;
    >
    > printf("\n len = %d\n",(*(*(p + 1) )).len); //line 1
    > printf("\n len = %d\n",(*(*++p) ).len); //line 2
    >
    >
    > return 0;
    > }
    > Here p is array 10 of pointer to “struct test” and the value of p is
    > &p[0]. So if p is incremented it will be pointing to the next element
    > i.e p[1].
    > According to me line 1 and line 2 is identical. But then why line 2 is
    > not getting compiled?
    >
    > I am getting the following error
    > test.c: In function `main':
    > test.c:15: error: wrong type argument to increment
    >
    > My guess would be the value of p is not providing object context to +
    > +.
    > Is it correct?
    > But then why it is not providing? Is it providing value context?
    >


    It will not work, because an array is not the same as a pointer, I
    think. You cannot just change the base around...
    Johann Klammer, Jan 25, 2013
    #2
    1. Advertising

  3. somenath

    Shao Miller Guest

    On 1/24/2013 22:31, somenath wrote:
    > I am not able to figure out why the following progarm is not
    > compiling.
    >
    > #include<stdio.h>
    >
    > int main(void)
    > {
    > struct test {
    > int len;
    > char *str;
    > }*p[10];
    > struct test t = { 100,"hello world" };
    > struct test t1 = { 11,"HI world" };
    > p[0] = &t;
    > p[1] = &t1;
    >
    > printf("\n len = %d\n",(*(*(p + 1) )).len); //line 1
    > printf("\n len = %d\n",(*(*++p) ).len); //line 2
    >
    >
    > return 0;
    > }
    > Here p is array 10 of pointer to “struct test” and the value of p is
    > &p[0].


    Using "the value of p...is &p[0]" is a common "white lie". It is easy
    for many people to think of array expressions in this way, but strictly
    speaking, the value of an array is composed of the values of all of the
    elements.

    But you're right that the expression 'p', when used outside of unary
    '&', 'sizeof' and '_Alignof', yields a pointer with value equal to that
    of '&p[0]'.

    > So if p is incremented it will be pointing to the next element
    > i.e p[1].


    'p' is not a modifiable lvalue. You cannot increment 'p', because it is
    not a pointer. It just so happens that when used outside of the
    operators I mentioned above, it undergoes conversion and yields a
    pointer value. That pointer value can be used, but not modified.

    > According to me line 1 and line 2 is identical. But then why line 2 is
    > not getting compiled?
    >
    > I am getting the following error
    > test.c: In function `main':
    > test.c:15: error: wrong type argument to increment
    >
    > My guess would be the value of p is not providing object context to +
    > +.
    > Is it correct?
    > But then why it is not providing? Is it providing value context?
    >


    If you add to the "white lie" that 'p' is a _constant_ pointer, then you
    can understand why you cannot increment it, but you can use it for
    pointer arithmetic.

    If you'd like to, please feel free to see "Array Decay" at:

    http://www.iso-9899.info/wiki/Code_snippets

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Jan 25, 2013
    #3
  4. somenath

    James Kuyper Guest

    On 01/24/2013 10:31 PM, somenath wrote:
    > I am not able to figure out why the following progarm is not
    > compiling.
    >
    > #include<stdio.h>
    >
    > int main(void)
    > {
    > struct test {
    > int len;
    > char *str;
    > }*p[10];
    > struct test t = { 100,"hello world" };
    > struct test t1 = { 11,"HI world" };
    > p[0] = &t;
    > p[1] = &t1;
    >
    > printf("\n len = %d\n",(*(*(p + 1) )).len); //line 1
    > printf("\n len = %d\n",(*(*++p) ).len); //line 2
    >
    >
    > return 0;
    > }
    > Here p is array 10 of pointer to �struct test� and the value of p is
    > &p[0]. So if p is incremented it will be pointing to the next element
    > i.e p[1].
    > According to me line 1 and line 2 is identical. But then why line 2 is
    > not getting compiled?


    The ++ operator requires an lvalue as it's operand - something which
    identifies an object of the type to be incremented. In most contexts, a
    lvalue of array type is automatically converted to a pointer value, but
    that pointer value is not an lvalue; it doesn't identify an object that
    is capable of being incremented.

    If you want to increment a pointer object, you'll have to re-write your
    code to include a pointer object that can be incremented:

    struct test **q = p;

    printf("\n len = %d\n",(*(*(q + 1) )).len); //line 1
    printf("\n len = %d\n",(*(*++q) ).len); //line 2


    > I am getting the following error
    > test.c: In function `main':
    > test.c:15: error: wrong type argument to increment
    >
    > My guess would be the value of p is not providing object context to +
    > +.
    > Is it correct?


    An "object context" is not standard C jargon, but that sounds like one
    way you could describe the problem.

    > But then why it is not providing? Is it providing value context?


    It would be more accurate to say that you're the one who failed to
    providing a pointer object to be incremented. Without such an object,
    there can be no relevant "object context".
    --
    James Kuyper
    James Kuyper, Jan 25, 2013
    #4
  5. somenath <> writes:
    > I am not able to figure out why the following progarm is not
    > compiling.
    >
    > #include<stdio.h>
    >
    > int main(void)
    > {
    > struct test {
    > int len;
    > char *str;
    > }*p[10];
    > struct test t = { 100,"hello world" };
    > struct test t1 = { 11,"HI world" };
    > p[0] = &t;
    > p[1] = &t1;
    >
    > printf("\n len = %d\n",(*(*(p + 1) )).len); //line 1
    > printf("\n len = %d\n",(*(*++p) ).len); //line 2
    >
    >
    > return 0;
    > }
    > Here p is array 10 of pointer to “struct test†and the value of p is
    > &p[0]. So if p is incremented it will be pointing to the next element
    > i.e p[1].
    > According to me line 1 and line 2 is identical. But then why line 2 is
    > not getting compiled?

    [...]

    Are you assuming that `p + 1` and `++p` are identical? They're not.
    `p + 1` simply yields the value of p with 1 added to it. `++p` also
    yields that same value, but as a side effect it stores `p + 1` in p.

    p is an array object, so the expression `p`, in most contexts,
    decays to a pointer to the first element of the array. `p + 1` is
    a perfectly valid expression; it's the address of `p[1]`. But since
    p is not a pointer object, you can't store a new pointer value in it.

    `++p` is illegal because p is an array object, and you can't assign
    to it. But even if p were a pointer object, `p + 1` and `++p`
    are not equivalent, since the latter has a side effect (and would
    be illegal if p were, for example, a const pointer object).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jan 25, 2013
    #5
  6. somenath

    somenath Guest

    On Jan 25, 11:10 pm, Keith Thompson <> wrote:
    > somenath <> writes:
    > > I am not able to figure out why the following progarm is not
    > > compiling.

    >
    > > #include<stdio.h>

    >
    > > int main(void)
    > > {
    > >     struct test {
    > >    int len;
    > >    char *str;
    > >     }*p[10];
    > >     struct test t = { 100,"hello world" };
    > >     struct test t1 = { 11,"HI world" };
    > >     p[0] = &t;
    > >     p[1] = &t1;

    >
    > >     printf("\n len = %d\n",(*(*(p + 1) )).len); //line 1
    > >     printf("\n len = %d\n",(*(*++p) ).len);  //line 2

    >
    > >     return 0;
    > > }
    > > Here p is array 10 of pointer to “struct test” and the value of p is
    > > &p[0]. So if p is incremented it will be pointing to the next element
    > > i.e p[1].
    > > According to me line 1 and line 2 is identical. But then why line 2 is
    > > not getting compiled?

    >
    > [...]
    >
    > Are you assuming that `p + 1` and `++p` are identical?  They're not.
    > `p + 1` simply yields the value of p with 1 added to it.  `++p` also
    > yields that same value, but as a side effect it stores `p + 1` in p.
    >
    > p is an array object, so the expression `p`, in most contexts,
    > decays to a pointer to the first element of the array.  `p + 1` is
    > a perfectly valid expression; it's the address of `p[1]`.  But since
    > p is not a pointer object, you can't store a new pointer value in it.
    >
    > `++p` is illegal because p is an array object, and you can't assign
    > to it.  But even if p were a pointer object, `p + 1` and `++p`
    > are not equivalent, since the latter has a side effect (and would
    > be illegal if p were, for example, a const pointer object).
    >


    Thanks all for the responses.

    I have almost got the reason that value of p is not modifiable.
    But I was able to visualize that.

    I often come across situation where I will be able to guess the
    answer but will not be able to convince myself that this is the
    right answer.
    I am not sure how to go about this. Is it good idea to look at the
    generated assembly code and then try to figure out the issue?
    What normally experts like all of you do when you are in this
    situation?
    Or normally you don’t fall into to such situation
    where you do not have convincing reason?
    somenath, Jan 26, 2013
    #6
  7. somenath <> wrote:

    (snip)
    > Thanks all for the responses.


    > I have almost got the reason that value of p is not modifiable.
    > But I was able to visualize that.


    > I often come across situation where I will be able to guess the
    > answer but will not be able to convince myself that this is the
    > right answer.


    > I am not sure how to go about this. Is it good idea to look at the
    > generated assembly code and then try to figure out the issue?
    > What normally experts like all of you do when you are in this
    > situation?
    > Or normally you don???t fall into to such situation
    > where you do not have convincing reason?


    There are cases where that is useful, but not ones that generate
    error conditions such that no code is generated.

    Mostly it is useful for checking how well a compiler optimizes
    something that can be done in different ways.

    -- glen
    glen herrmannsfeldt, Jan 26, 2013
    #7
  8. somenath

    James Kuyper Guest

    On 01/25/2013 09:42 PM, somenath wrote:
    > On Jan 25, 11:10�pm, Keith Thompson <> wrote:
    >> somenath <> writes:
    >>> I am not able to figure out why the following progarm is not
    >>> compiling.

    >>
    >>> #include<stdio.h>

    >>
    >>> int main(void)
    >>> {
    >>> � � struct test {
    >>> � �int len;
    >>> � �char *str;
    >>> � � }*p[10];
    >>> � � struct test t = { 100,"hello world" };
    >>> � � struct test t1 = { 11,"HI world" };
    >>> � � p[0] = &t;
    >>> � � p[1] = &t1;

    >>
    >>> � � printf("\n len = %d\n",(*(*(p + 1) )).len); //line 1
    >>> � � printf("\n len = %d\n",(*(*++p) ).len); �//line 2

    >>
    >>> � � return 0;
    >>> }
    >>> Here p is array 10 of pointer to �struct test� and the value of p is
    >>> &p[0]. So if p is incremented it will be pointing to the next element
    >>> i.e p[1].
    >>> According to me line 1 and line 2 is identical. But then why line 2 is
    >>> not getting compiled?

    >>
    >> [...]
    >>
    >> Are you assuming that `p + 1` and `++p` are identical? �They're not.
    >> `p + 1` simply yields the value of p with 1 added to it. �`++p` also
    >> yields that same value, but as a side effect it stores `p + 1` in p.
    >>
    >> p is an array object, so the expression `p`, in most contexts,
    >> decays to a pointer to the first element of the array. �`p + 1` is
    >> a perfectly valid expression; it's the address of `p[1]`. �But since
    >> p is not a pointer object, you can't store a new pointer value in it.
    >>
    >> `++p` is illegal because p is an array object, and you can't assign
    >> to it. �But even if p were a pointer object, `p + 1` and `++p`
    >> are not equivalent, since the latter has a side effect (and would
    >> be illegal if p were, for example, a const pointer object).
    >>

    >
    > Thanks all for the responses.
    >
    > I have almost got the reason that value of p is not modifiable.


    While you can't modify the entire array at one time, The elements of the
    array are individually modifiable. In fact, your code modifies both p[0]
    and p[1], without any problems. However, in most C contexts, an lvalue
    of array type is implicitly converted to a pointer to the first element
    of the array. That pointer value is not stored in any C object, and is
    therefor not modifiable. Understand that rule, and everything else follows.

    It might be help to understand what happens to p in the following code:

    p[1] = &t1;

    In this context, the expression 'p' is converted to a pointer to the
    first element of the array named 'p'. By definition, p[1] is equivalent
    to *(p+1), so that pointer is advanced by one element, to point at the
    second element of the array. Then that pointer is dereferenced,
    producing an lvalue referring to the second element of that array. Since
    p[1] is the left operand of an assignment expression, the result of that
    assignment expression is to set the second element of p to the value &t1.

    > But I was able to visualize that.


    That sentence would make slightly better sense, in context, if you meant
    "unable" rather than "able". Is that what you meant?

    > I often come across situation where I will be able to guess the
    > answer but will not be able to convince myself that this is the
    > right answer.
    > I am not sure how to go about this. Is it good idea to look at the
    > generated assembly code and then try to figure out the issue?


    I don't think so. Your fundamental problem is that you think that
    expression p++ is meaningful in this context, but the C standard
    disagrees. As a result, as you've discovered, this particular compiler
    won't generate any assembly code for you to look at. I think you'll find
    that most compilers do the same.

    While a conforming implementation of C must issue at least one
    diagnostic message for such code, after doing so it is then free to do
    whatever it wants with it. In the unlikely event that you found a
    different compiler which did decide to generate assembly code for that
    construct, it would be implementing an extension to C. That generated
    code could tell you a lot about that extension, but it won't tell you
    anything about why the C standard makes such code a constraint violation.

    The C standard could have been written to make such code meaningful.
    Examining the generated object code won't tell you why it wasn't written
    that way.

    > What normally experts like all of you do when you are in this
    > situation?
    > Or normally you don�t fall into to such situation
    > where you do not have convincing reason?


    Not understanding the reason for something is less common when you get
    more knowledge of the C standard, but even the best of us still run into
    that situation occasionally. My approach is to read the standard and
    carefully understand what it says. If you have trouble understanding it,
    ask questions of those who understand it better. It's also entirely
    possible that it doesn't make sense - but I'd recommend waiting until
    you're much more familiar with the standard before filing a defect report.
    --
    James Kuyper
    James Kuyper, Jan 26, 2013
    #8
    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. velthuijsen
    Replies:
    4
    Views:
    352
    velthuijsen
    May 10, 2004
  2. Juri
    Replies:
    5
    Views:
    366
    Rob Williscroft
    Jun 15, 2004
  3. somenath
    Replies:
    4
    Views:
    291
  4. somenath
    Replies:
    0
    Views:
    258
    somenath
    Dec 14, 2007
  5. Goran
    Replies:
    4
    Views:
    350
    Frank Birbacher
    May 23, 2008
Loading...

Share This Page