Basic pointers question

S

Simon

I'm trying to understand pointers in a little more detail, and have
written a test program (reproduced below) to experiment with passing
pointers between functions.

Thinking only about the variable x in main, I would expect the
following to happen:
- &x is passed to func_one, so int* p1x is pointing to x (int* p1x =
&x)
- func_one then dereferences p1x to increment x; at this point x = 1
- func_one passes p1x to func_two, so int* p2x = p1x and pointers p2x
and p1x both point to x
- func_two then dereferences p2x to increment x; at this point x = 2
- control passes back to main() and the value of x is printed

Therefore, I would expect this program to produce the output "x = 2; y
= 2; c = 1", but it doesn't. Can anyone provide any insight into why
this is the case?

Thanks in advance

Simon


--code follows --

#include <stdio.h>

void func_two (int* p2x, int* p2y)
{
*px ++;
*py ++;
}

void func_one (int* p1x, int* p1y, int* p1c)
{
*pc ++;
*px ++;
*py ++;
func_two (px, py);
}

int main (void)
{
int x, y, c, d;
x = y = c = 0;
func_one (&x, &y, &c);
printf("x = %d; y = %d; c = %d", x, y, c);
d = getchar();
return 0;
}
 
R

Richard Heathfield

Simon said:
I'm trying to understand pointers in a little more detail, and have
written a test program (reproduced below) to experiment with passing
pointers between functions.

Thinking only about the variable x in main, I would expect the
following to happen:
- &x is passed to func_one, so int* p1x is pointing to x (int* p1x =
&x)
- func_one then dereferences p1x to increment x; at this point x = 1

Here is your mistake. *p1x++ does not increment x (the int pointed to by
p1x)!

This is what happens. Firstly, we need to evaluate p1x++ (because the
grammar says so). The result of this evaluation is the prior value of p1x
(because ++ is POST-increment), and the side effect is to increment p1x at
some time before the next sequence point. The result of the evaluation, as
I say, is the /prior/ value of p1x, which is of course still a pointer to
your original int. The * is then applied to this pointer value, yielding
the value of x, with which you do nothing.

If you want to increment x through p1x, you can do this:

++*p1x;

or this:

(*p1x)++;

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
S

Simon

Richard said:
Here is your mistake. *p1x++ does not increment x (the int pointed to by
p1x)!

Argh!!! - I new it was something simple! I forgot the relative binding
strengths of ++ and *.

Incidentally - there was another mistake in the code above which was
due to me mis-typing it into Google Groups. All now works perfectly -
thanks a lot for your help!

Simon
 
C

Chris Dollin

Simon said:
I'm trying to understand pointers in a little more detail,

There is hardly any detail to know. Really.
void func_two (int* p2x, int* p2y)
{
*px ++;

Dereference `px` and throw the value away. Increment `px`.

I suspect you meant `(*px)++`, which I would write as
`*px += 1` because I think that makes what's going on clearer.
 
J

junky_fellow

Richard said:
Simon said:

This is what happens. Firstly, we need to evaluate p1x++ (because the
grammar says so). > (*p1x)++;

I would request to kindly elaborate on this. I mean to say how from the
C grammar
we can determine this ? In some of the posts, that I read earlier in
this newsgroup
I came to know that C grammar does not specify any precedence. So,
using the C
grammar how post decrement operator is evaluated before the unary
(pointer) operator.
I was looking at the lex and yacc grammar of C, which I downloaded from
the
following links:
http://www.lysator.liu.se/c/ANSI-C-grammar-l.html (lex file)
http://www.lysator.liu.se/c/ANSI-C-grammar-y.html#declaration (yacc
file)

Can you please explain how the expression (*p1x++) will be evaluated
using the
lex and yacc files at the above mentioned links ?

thanks a lot for any help in advance ....
 
C

Chris Dollin

I would request to kindly elaborate on this. I mean to say how from the
C grammar we can determine this ?

We look at the productions of the grammar and the meaning of the
constructs.
In some of the posts, that I read earlier in
this newsgroup I came to know that C grammar does not specify any precedence.

More accurately, the C grammar does not use the idea of "precedence"
to disambiguate its expression grammar. It just uses an unambiguous
grammar.

In the expression `*p++`, there are only a few productions of interest.
Here is a (strongly selected) view:

primary-expression:
identifier

postfix-expression:
postfix-expression ++
primary-expression

unary-expression:
unary-operator postfix-expression

unary-operator:
*
expression: ... eventually, unary-expression ...

We see from this that `*p++` /must/ be parsed as the unary-operator
`*` applied to the postfix-expression `p++`. There's no other way
to do it (the other productions of the grammar don't help).
So, using the C grammar how post decrement operator is evaluated
before the unary (pointer) operator.

The evaluation rules are different from the grammar. The grammar
says how expressions are /structured/. The evaluation rules tell
you how those structures are /evaluated/. They're in the
Standard, but I expect they're not in the gramamr files you
downloaded, since they're not part of the grammar.

To evaluate `*p++`, we evaluate the unary-expression with operator
`*` and operand `p++`, because that's how it is parsed. To evaluate
`*E`, we evaluate `E` and then dereference the result. Here `E` is
`p++`. To evaluate `X++`, we get the lvalue `X`, deliver its
current value, and note that we must increment `X` by the next
sequence point. So we return the value of `p` (which will be
dereferenced by the `*`) and will eventually increment in. In
the original post, `*p++` is the full expression forming the body
of the expression-statement `*p++;`, which supplies the sequence
point; after the semicolon, `p` will have been incrememented.
 
J

junky_fellow

In the expression `*p++`, there are only a few productions of interest.
Here is a (strongly selected) view:

primary-expression:
identifier

postfix-expression:
postfix-expression ++
primary-expression

unary-expression:
unary-operator postfix-expression

unary-operator:
*
expression: ... eventually, unary-expression ...

We see from this that `*p++` /must/ be parsed as the unary-operator
`*` applied to the postfix-expression `p++`. There's no other way
to do it (the other productions of the grammar don't help).

says how expressions are /structured/. The evaluation rules tell
you how those structures are /evaluated/. They're in the
Standard, but I expect they're not in the gramamr files you
downloaded, since they're not part of the grammar.

To evaluate `*p++`, we evaluate the unary-expression with operator
`*` and operand `p++`, because that's how it is parsed. To evaluate
`*E`, we evaluate `E` and then dereference the result. Here `E` is
`p++`. To evaluate `X++`, we get the lvalue `X`, deliver its
current value, and note that we must increment `X` by the next
sequence point. So we return the value of `p` (which will be
dereferenced by the `*`) and will eventually increment in. In
the original post, `*p++` is the full expression forming the body
of the expression-statement `*p++;`, which supplies the sequence
point; after the semicolon, `p` will have been incrememented.

Thanks Chris for the nice explanation. thanks a lot.
 

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,011
Latest member
AjaUqq1950

Latest Threads

Top