开发者

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 rea开发者_JS百科l 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.


*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        
}


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


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++;


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.


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++;


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).


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.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜