question regarding ++ operator.

S

somenath

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?
 
J

Johann Klammer

somenath said:
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...
 
S

Shao Miller

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
 
J

James Kuyper

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".
 
K

Keith Thompson

somenath said:
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).
 
S

somenath

somenath said:
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?
 
G

glen herrmannsfeldt

(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
 
J

James Kuyper

somenath said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top