Strange behavior with pointers

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have created a program that accesses a flat 2 dimensional array and have
developed a routine to sum the four neighbors of a specific row/column
position.

Here is an example, this will sum all the values of row 1, column 1 (base 0)
which is the number 5


int a[9] = {1,2,3,4,5,6,7,8,9};
int* pa = &a[3]; // row 1, column 0 (i.e. number 4)
int n = *(pa++); // n = 4
n += *(++pa); // n = 10 (4 + 6)
n += *(--pa - 3); // n = 12 (10 + 2)
n += *(pa + 3); // n = 20 (12 + 8)

Now here is the strange part if I combine all the code above into one
statement

n = *(pa++) + *(++pa) + *(--pa - 3) + *(pa + 3);

I don't get the same results, instead of 20 I get 18. Am I missing something
here is this a compiler or programming error?

Any help would be greatly appreciated
 
John said:
I have created a program that accesses a flat 2 dimensional array and have
developed a routine to sum the four neighbors of a specific row/column
position.

Here is an example, this will sum all the values of row 1, column 1 (base
0)
which is the number 5


int a[9] = {1,2,3,4,5,6,7,8,9};
int* pa = &a[3]; // row 1, column 0 (i.e. number 4)
int n = *(pa++); // n = 4
n += *(++pa); // n = 10 (4 + 6)
n += *(--pa - 3); // n = 12 (10 + 2)
n += *(pa + 3); // n = 20 (12 + 8)

Now here is the strange part if I combine all the code above into one
statement

n = *(pa++) + *(++pa) + *(--pa - 3) + *(pa + 3);

I don't get the same results, instead of 20 I get 18. Am I missing
something
here is this a compiler or programming error?

Any help would be greatly appreciated

Something I see right off the bat is...what happens to pa before and after
combining this to the statement? If you follow pa through you get the
following:

int* pa = &a[3]; -- pa == 4
int n = *(pa++); -- pa == 4
n += *(++pa); -- pa == 6
n += *(--pa -3) -- pa == 5
n += *(pa + 3) -- pa == 5

so, putting that together we get: (4 + 6 + 5 + 5)..

Putting it together on one line like you have it means...

n = *(pa++) + *(++pa) + *(--pa - 3) + *(pa + 3) means the following:

n = pa++ (pa holds a value of 4) + (pa holds a value of 6) + (pa holds a
value of 4) - 3 + (pa holds a value of 4) + 3

the first pa++ is evaluated then incremented (use in expression then add 1
to pa)...value used is 4
the ++pa is incremented then evaluated (add 1 to pa then use in
expression)...value used is 6 (previous value used was 4 but previous calc
for pa was pa++ and therefore it was incremented to 5. This ++pa adds 1 to
5 which makes it 6.)
Then, --pa is decremented then evalueated (subtracts 1 from pa [6 - 1] to
make 5) ... value used is 5
adds 3 to 5
Lastly, pa is 5 and it adds 3 to the 5 which makes 8.

so, we get....

(pa++ [pa evaluated as 4]) + ([pa is 5 before this] ++pa [pa is
preincremented and now is + 6]) + ([pa is still 6] --pa [now pa is 5]) - 3 +
([pa is still 5]5) + 3

4 + 6 + 5 - 3 + 5 + 3 = 18

Hope this helps :)

Mythran

ps. haven't done this in years....feels good still being able to do
it...albeit, took me awhile longer than it should have to remember...I'm
getting old!
 
John said:
I have created a program that accesses a flat 2 dimensional array and
have
developed a routine to sum the four neighbors of a specific row/column
position.

Here is an example, this will sum all the values of row 1, column 1
(base 0)
which is the number 5


int a[9] = {1,2,3,4,5,6,7,8,9};
int* pa = &a[3]; // row 1, column 0 (i.e. number 4)
int n = *(pa++); // n = 4
n += *(++pa); // n = 10 (4 + 6)
n += *(--pa - 3); // n = 12 (10 + 2)
n += *(pa + 3); // n = 20 (12 + 8)

Now here is the strange part if I combine all the code above into one
statement

n = *(pa++) + *(++pa) + *(--pa - 3) + *(pa + 3);

I don't get the same results, instead of 20 I get 18. Am I missing
something
here is this a compiler or programming error?

You cannot modify the same value (pa) more than once in each expression.
The order of evaluation is not defined in C and C++, so you cannot
predict the outcome. The compiler is allowed to do whatever it likes.


Bo Persson
 
Mythran said:
John said:
I have created a program that accesses a flat 2 dimensional array and
have
developed a routine to sum the four neighbors of a specific
row/column
position.

Here is an example, this will sum all the values of row 1, column 1
(base 0)
which is the number 5


int a[9] = {1,2,3,4,5,6,7,8,9};
int* pa = &a[3]; // row 1, column 0 (i.e. number 4)
int n = *(pa++); // n = 4
n += *(++pa); // n = 10 (4 + 6)
n += *(--pa - 3); // n = 12 (10 + 2)
n += *(pa + 3); // n = 20 (12 + 8)

Now here is the strange part if I combine all the code above into one
statement

n = *(pa++) + *(++pa) + *(--pa - 3) + *(pa + 3);

I don't get the same results, instead of 20 I get 18. Am I missing
something
here is this a compiler or programming error?

Any help would be greatly appreciated

Something I see right off the bat is...what happens to pa before and
after combining this to the statement? If you follow pa through you
get the following:

int* pa = &a[3]; -- pa == 4
int n = *(pa++); -- pa == 4
n += *(++pa); -- pa == 6
n += *(--pa -3) -- pa == 5
n += *(pa + 3) -- pa == 5

so, putting that together we get: (4 + 6 + 5 + 5)..

Putting it together on one line like you have it means...

n = *(pa++) + *(++pa) + *(--pa - 3) + *(pa + 3) means the following:

n = pa++ (pa holds a value of 4) + (pa holds a value of 6) + (pa holds
a value of 4) - 3 + (pa holds a value of 4) + 3

the first pa++ is evaluated then incremented (use in expression then
add 1 to pa)...value used is 4
the ++pa is incremented then evaluated (add 1 to pa then use in
expression)...value used is 6 (previous value used was 4 but previous
calc for pa was pa++ and therefore it was incremented to 5. This
++pa adds 1 to 5 which makes it 6.)
Then, --pa is decremented then evalueated (subtracts 1 from pa [6 - 1]
to make 5) ... value used is 5
adds 3 to 5
Lastly, pa is 5 and it adds 3 to the 5 which makes 8.

so, we get....

(pa++ [pa evaluated as 4]) + ([pa is 5 before this] ++pa [pa is
preincremented and now is + 6]) + ([pa is still 6] --pa [now pa is
5]) - 3 + ([pa is still 5]5) + 3

4 + 6 + 5 - 3 + 5 + 3 = 18

This is one possible way for the compiler to come to this result.
However, it is not required to chose this particular order. When a
variable is modified more that once in the same expression (formally
"between two sequence points"), any and all results are equally correct
and possible.

For Java, there is probably a defined order of evaluation, but for C and
C++ there is not.


Bo Persson
 
John said:
I have created a program that accesses a flat 2 dimensional array and have
developed a routine to sum the four neighbors of a specific row/column
position.

Here is an example, this will sum all the values of row 1, column 1 (base 0)
which is the number 5


int a[9] = {1,2,3,4,5,6,7,8,9};
int* pa = &a[3]; // row 1, column 0 (i.e. number 4)
int n = *(pa++); // n = 4
n += *(++pa); // n = 10 (4 + 6)
n += *(--pa - 3); // n = 12 (10 + 2)
n += *(pa + 3); // n = 20 (12 + 8)

Now here is the strange part if I combine all the code above into one
statement

n = *(pa++) + *(++pa) + *(--pa - 3) + *(pa + 3);

I don't get the same results, instead of 20 I get 18. Am I missing something
here is this a compiler or programming error?

Programming error. For more, see:

http://www.eskimo.com/~scs/C-faq/q3.2.html
http://www.research.att.com/~bs/bs_faq2.html#evaluation-order
 
Back
Top