P.Brian.Mackey
P.Brian.Mackey

Reputation: 44285

Order of operations for pointers

Can you please explain the order of operations for the following function that reverses a string?

//http://www.perlmonks.org/?node_id=589993 source of method
/* reverse a string in place, return str */
static char* reverse(char* str)
{
    char* left  = str;
    char* right = left + strlen(str) - 1;
    char  tmp;
    while (left < right)
    {
        tmp      = *left;
        *left++  = *right;//This part is real confusing...Does ++ happen after the assignment?
        *right-- = tmp;//This one is just as bad
    }
    return str;
}

I can follow the first 3 lines in the method pretty easily, but once it hits the while loop I am at a loss for how this works. Specifically the lines marked above. Thank you.

Upvotes: 0

Views: 1437

Answers (7)

ikegami
ikegami

Reputation: 386396

Does ++ happen after the assignment?

No. The increment of p probably happens before the assignment occurs, but that's not really important here.

The important part is that the assignment only sees the value p had before p was incremented. p++ no more returns p than !x returns x.

p++ returns the original value of p along the same lines as

TYPE* post_inc(TYPE* p) {
   TYPE* tmp = p;
   ++p;
   return tmp;
}

All together, it looks something like:

    tmp = *left;

    anon0 = left;
    ++left;
    *anon0 = *right;

    anon1 = right;
    --right;
    *anon1 = tmp;

(Actual order may vary some.)

Upvotes: 0

Jeff Mercado
Jeff Mercado

Reputation: 134521

You got it.

*left++  = *right;
  1. dereference *right
  2. store (1) at *left
  3. increment left

 

*right-- = tmp;
  1. store tmp at *right
  2. decrement right

Postfix increment/decrement (++/--) operators have the higher precedence than dereferencing (*). So *left++ is parsed as *(left++). Being a post increment operation, the incrementation occurs after this sequence (i.e., after the assignment takes place).

Upvotes: 0

John Bode
John Bode

Reputation: 123558

Postfix operators (which include ++ and --) have higher precedence than unary operators (such as *). Thus, the expression *p++ is parsed as *(p++), so the * is applied to the result of p++.

So,

*left++ = *right;

is equivalent to

*left = *right;
left++;

Upvotes: 0

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215447

This line:

*left++ = *right;

has two side effects: left is incremented to point to the next element of the array it's pointing to, and the value read from the address right is stored at the location left pointed to prior to the increment. However there is no ordering defined between whether the storage to the pointer variable left happens before or after the storage to the character it pointed to.

Upvotes: 0

Lindydancer
Lindydancer

Reputation: 26124

To understand the code, it's easier if you add parentheses to it:

*left++  = *right;

Is the same as:

*(left++) = *right;

On other words, the ++ is applied to the pointer, not to what the pointer points to.

As this is the post increment operator, the side effect takes place after the value of left has been used. In other words, this is the same as:

*left = *right;
left++;

Upvotes: 0

user2100815
user2100815

Reputation:

The post decrement operators happen after the dereference, and so effectively (in your code) after the assignment.

Upvotes: 0

Chris Eberle
Chris Eberle

Reputation: 48795

*left++  = *right

In this statement, *left is assigned *right, and then after all of that left (not *left) is incremented. The same logic goes for *right--

So rewritten, the pseudocode would be this:

while(not halfway)
{
    tmp = left value
    left value = right value
    left position += 1
    right value = tmp
    right position -= 1        
}

Upvotes: 4

Related Questions