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;
- dereference
*right
- store (1) at
*left
- increment
left
*right-- = tmp;
- store
tmp
at*right
- 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.)
精彩评论