operator precedance

J

Joseph

I am having difficulty understanding this piece of code. I don't
understand why ++*ptr prints 7 and *ptr-- prints an unknown value. I
would have expected it to print 8. I would have to put brackets (*ptr)--
for it work. Thanx in advance.

Joseph

#include <stdio.h>

int main(void)
{
int ctr =6;
int *ptr=&ctr;

++*ptr;
printf("ptr=%d\n", *ptr); /*prints 7*/

*ptr++;
printf("ptr=%d\n", *ptr); /* prints ? */
}
 
E

Eric Sosman

Joseph said:
I am having difficulty understanding this piece of code. I don't
understand why ++*ptr prints 7 and *ptr-- prints an unknown value. I
would have expected it to print 8. I would have to put brackets (*ptr)--
for it work. Thanx in advance.

#include <stdio.h>

int main(void)
{
int ctr =6;
int *ptr=&ctr;

++*ptr;
printf("ptr=%d\n", *ptr); /*prints 7*/

Right. `++*ptr' is equivalent to `++(*ptr)', which
is equivalent to `++(ctr)', which is equivalent to `++ctr'.
Since `ctr' starts out with the value six, `++ctr' changes
it to seven and yields seven as the value (which is then
discarded). `ptr' itself is not changed, so when you get
to the printf() call `*ptr' is still equivalent to `ctr',
which now has the value seven.
*ptr++;
printf("ptr=%d\n", *ptr); /* prints ? */

Might print anything at all, or nothing, or make demons
fly from your nostrils. Let's go through it: `*ptr++' is
equivalent to `*(ptr++)'. The `ptr++' piece does two things:
it increments `ptr' and yields the value `ptr' had prior to
being incremented. So `*(ptr++)' is equivalent to `(ctr)'
plus the side-effect of incrementing `ptr'. Now when you
get to the printf() call, `ptr' no longer points to `ctr'
because it has been incremented; it points to something "one
slot past the end" of `ctr'. There may or may not actually
be anything at this spot; if something does dwell there it
may or may not be an `int'. You are sticking your hand into
a sack without any idea what's inside: it might be an `int',
or it might be a piece of salt-water taffy, or it might be
an enraged cobra. Don't Do That.
 
M

Mark A. Odell

I am having difficulty understanding this piece of code. I don't
understand why ++*ptr prints 7 and *ptr-- prints an unknown value. I
would have expected it to print 8. I would have to put brackets (*ptr)--
for it work. Thanx in advance.

Joseph

#include <stdio.h>

int main(void)
{
int ctr =6;
int *ptr=&ctr;

++*ptr;
printf("ptr=%d\n", *ptr); /*prints 7*/

*ptr++;
printf("ptr=%d\n", *ptr); /* prints ? */
}

From:

http://freebsd.ntu.edu.tw/bsd/13/7/21.html

Since they associate right to left, with greedy operator binding we get:

++(*ptr)

or

"increment the dereferenced value of ptr" which is 7.

Next case, same rule we get:

*(ptr++)

or

"increment beyond the address of 'ctr' and then dereference it" which in
this case would be junk.
 
M

Martijn

A slightly different table, containing mostly the same information, but also
the direction of associativity.

Operator Precedence and Associativity Rules in C / C++

============================================================================
:: scope resolution (C++, e.g. name::member) left-to-right
:: global (C++, e.g. ::name)
---------------------------------------------------------------------------
-
( ) function call left-to-right
[ ] array element
. class, structure or union member
-> pointer reference to member
:: scope access / resolution (C++)
sizeof size of object in bytes
sizeof size of type in bytes
---------------------------------------------------------------------------
-
++ post increment (lvalue++) right-to-left
++ pre increment (++lvalue)
-- post decrement (lvalue--)
-- pre decrement (--lvalue)
~ bitwise complement
! logical not
- unary minus
+ unary plus
& address of
* contents of
new create object (C++)
delete destroy object (C++)
delete[] destroy array (C++)
(type) cast to type
---------------------------------------------------------------------------
-
.* member pointer (C++) left-to-right
->* pointer reference to member pointer (C++)
---------------------------------------------------------------------------
-
* multiply left-to-right
/ divide
% remainder
---------------------------------------------------------------------------
-
+ add left-to-right
- subtract
---------------------------------------------------------------------------
-
<< bitwise left shift left-to-right ---------------------------------------------------------------------------
-
< scalar less than left-to-right
<= scalar less than or equal to
> scalar greater than
>= scalar greater than or equal to
---------------------------------------------------------------------------
-
== scalar equal left-to-right
!= scalar not equal
---------------------------------------------------------------------------
-
& bitwise and left-to-right
---------------------------------------------------------------------------
-
^ bitwise exclusive or left-to-right
---------------------------------------------------------------------------
-
| bitwise or left-to-right
---------------------------------------------------------------------------
-
&& logical and left-to-right
---------------------------------------------------------------------------
-
|| logical inclusive or left-to-right
---------------------------------------------------------------------------
-
? : conditional expression right-to-left
---------------------------------------------------------------------------
-
= assignment operator right-to-left
also += -= *= /= %=
&= ^= |= >>= <<=
---------------------------------------------------------------------------
-
, sequential expression left-to-right
---------------------------------------------------------------------------
-

All of the operators in this table can be overloaded (C++) except:

. C++ direct component selector
.* C++ dereference
:: C++ scope access/resolution
?: Conditional
 
M

Mac

From:

http://freebsd.ntu.edu.tw/bsd/13/7/21.html

Since they associate right to left, with greedy operator binding we get:

++(*ptr)

or

"increment the dereferenced value of ptr" which is 7.

Next case, same rule we get:

*(ptr++)

or

"increment beyond the address of 'ctr' and then dereference it" which in
this case would be junk.

Oh, no. that line isn't the problem. The value which is dereferenced in
this line of code is the value ptr held before it was incremented. So, the
value of *(ptr++) is well behaved, and is not by itself illegal, although
it does leave ptr pointing beyond a valid object.

The real problem comes later when ptr, which now points beyond a valid object,
is dereferenced in the printf statement.

Mac
--
 
M

Mark A. Odell

Mac said:
Oh, no. that line isn't the problem. The value which is dereferenced in
this line of code is the value ptr held before it was incremented. So,
the value of *(ptr++) is well behaved, and is not by itself illegal,
although it does leave ptr pointing beyond a valid object.

The real problem comes later when ptr, which now points beyond a valid
object, is dereferenced in the printf statement.

Ugh. What was I thinking? Thank you for the correction.
 

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,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top