This question already has answers here:
Post-increment on a dereferenced pointer?
(13 answers)
Closed 8 years ago.
I'm not really sure what the order here is. Is it:
1) Dereference the value of pointer p after increasing it
2) Dereference the value of pointer p before increasing it
There is no ordering between the increment and the dereference. However, the * operator applies to the result of p++, which is the original value of p prior to the increment.
In the operators table, you can see that the suffix operator ++ have higher place than the * unary operator.
Hence, *p++ increase p (and not *p), and return the value of the address that p contained before the increment (since it's the suffix ++).
But the order is implementation-depend. It may begin by dereferencing p, and then increase it, and it may store the old value of p, increase it, and then dereference the old value.
Try it. The program
#include <stdio.h>
int main(void) {
int p[2];
int *q = p;
p[0] = 10;
p[1] = 100;
printf("%d\n", *q++);
printf("%d\n", *q);
return 0;
}
prints
10
100
showing that the ++ applies to p, not to *p, and that the increment happens after the dereference.
EDIT: (Thanks to #EricLippert for convincing me to pull out K & R)
Not only may there be a happens-after relationship, but according to K & R page 203, there must be:
A postfix expression followed by a ++ or -- operator is a postfix expression. The value of the expression of the expression is the value of the operand. After the value is noted, the operand is incremented (++) or decremented (--) by 1.
(emphasis mine)
Granted, I don't believe that K & R says anything about the semantics of C in the presence of multithreading (according to Wikipedia the pthreads specification was released in 1995), but for a single-threaded program K & R is pretty clear.
Given q = *p++;, q gets the value that p pointed to before the increment. Another way to say it is that the value of the expression *p++ is the value that p pointed to before being incremented.
The postfix ++ and -- operators essentially have higher precedence than the prefix unary operators. Therefore, *p++ is equivalent to *(p++); it increments p, and returns the value which p pointed to before p was incremented.
To increment the value pointed to by p, use (*p)++ (or perhaps ++*p, if the evaluation order of the side effect doesn't matter).
Related
As per C, PostIncrement(a++) > Dereference(*) > Assignment(=)
When I execute this below c snippet,
#include <stdio.h>
int main(){
int arr[]= {1,2,3};
int *p = a;
*p++ = 3;
for(int i=0;i<3;i++){
printf("%d ",arr[i]);
}
}
Output:
3 2 3
But if we apply order of precedence in this statement,
*p++ = 3;
The statement will be evaluated in the following order:
p++ will be evaluated
*p will get dereferenced.
then 3 will be assigned to *p using the assignment operator
If we apply the above order,
p which is pointing to the start of the array arr, will get incremented first and point to the second element of the array. Then second element's address will get dereferenced and then 3 will be assigned to the second index. So our expected output should be 1 3 3
But the output I got is 3 2 3.
I know that my expected output is not correct. It'll be helpful if you explain the order of evaluation here in this case of the output of the compiler.
Precedence only determines the grouping of operators with operands - it does not control the order in which expressions are evaluated. Precedence rules only determine that
*p++ = 3;
should parsed as
*(p++) = 3; // as opposed to (*p)++ = 3 or *(p++ = 3)
not that operations be executed in a specific order.
The ++ and –– operators have a result and a side effect. The result of postfix ++ is the current value of the operand; the side effect is to increment the operand. Your expression is logically equivalent to
tmp = p;
*tmp = 3;
p = p + 1;
with the caveat that the assignment to *tmp and the update of ptr can happen in any order, and they can even be interleaved or executed in parallel.
The result of a post-increment expression is the value of the operand before it is incremented. Thus, even though the ++ in *p++ does, indeed, have higher precedence than the *, the latter is applied to the result of the p++ expression which is, as just mentioned, the initial value of p.
According to the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the operand.
As a side effect, the value of the operand object is incremented (that
is, the value 1 of the appropriate type is added to it). See the
discussions of additive operators and compound assignment for
information on constraints, types, and conversions and the effects of
operations on pointers. The value computation of the result is
sequenced before the side effect of updating the stored value of the
operand. With respect to an indeterminately-sequenced function call,
the operation of postfix ++ is a single evaluation. Postfix ++ on an
object with atomic type is a read-modify-write operation with
memory_order_seq_cst memory order semantics.
Thus in this statement
*p++ = 3;
the expression p++ returns the current value of the pointer p that is a pointer that points to the first element of the array. It is this pointer to the first element of the array that is dereferenced.
So this statement
*p++ = 3;
is not equivalent to the statements
p++;
*p = 3;
"The statement will be evaluated in the following order:
p++ will be evaluated
*p will get dereferenced.
then 3 will be assigned to *p using the assignment operator"
Post Increments operator doesn't work like that. You can assume like this for better understanding.
When p++ gets evaluated, first, its present value is stored at a temporary location then the increment takes places.
All remaining operations are performed on the value stored in temporary location.
For subsequent statements incremented value is used.
This question already has an answer here:
In which order are the increment expressions on the right evaluated in the assignment statement? Is it undefined?
(1 answer)
Closed 4 years ago.
Consider the below program
#include <stdio.h>
void main(){
int p = -8;
int i = (p++, ++p);
printf("%d\n", i);
}
I am unable to get why the output is -6.
p++ would increment after the assignment statement is executed, ++p will increment before thereby making -8 to -7.
How i is assigned -6?
Because for a comma operator A,B then A is done first then B, and p++ increment the p, and ++p also increment the p. Operator precedence.
Or think like this
int i = (p++, ++p);
is
p++;
int i = ++p;
The expression (p++, ++p) has a comma operator. The comma operator evaluates its operand left-to-right and yields the result of the right most operand. Thus i gets the value -6 (after p++ and ++p operations).
as ptr_user7813604 said, you are using the comma operator which is a binary operator in c.
It evaluates it's first operand (in your case p++ increments p) and then discards the result (meaning p was incremented but not assigned to any variable) and then it evaluates the second operand (in your case ++p increments p) and returns this value and type. because the second operand is ++p so you receive the value after it was incremented, if the second operand was another p++ you would have assigned to i the value before it was incremented.
for additional information about the comma operator you can look up https://en.wikipedia.org/wiki/Comma_operator.
I found this text (source: https://education.cppinstitute.org/) and I'm trying to understand the second instruction.
Can you answer the question of what distinguishes these two instructions?
c = *p++;
and
c = (*p)++;
We can explain: the first assignment is as if the following two disjoint instructions have been performed;
c = *p;
p++;
In other words, the character pointed to by p is copied to the c variable; then, p is increased and points to the next element of the array.
The second assignment is performed as follows:
c = *p;
string[1]++;
The p pointer is not changed and still points to the second element of the array, and only this element is increased by 1.
What I don't understand is why it is not incremented when the = operator has less priority than the ++ operator.
With respect to this statement expression
c = (*p)++;
, you say
What i dont understand is why [p] is not incremented when the =
operator has less priority than the ++ operator.
There is a very simple explanation: p is not incremented as a result of evaluating that expression because it is not the operand of the ++ operator.
That is in part exactly because the = operator has lower precedence: because the precedence of = is so low, the operand of ++ is the expression (*p) rather than the expression c = (*p). Note in particular that p itself is not even plausibly in the running to be the operand in that case, unlike in the variation without parentheses.
Moving on, the expression (*p) designates the thing to which p points, just as *p all alone would do. Context suggests that at that time, that's the same thing designated by string[1]. That is what gets incremented, just as the text says, and its value prior to the increment is the result of the postfix ++ operation.
What I don't understand is why it is not incremented when the = operator has less priority than the ++ operator.
The value for example of the expression
x++
is the value of x before incrementing.
So if you'll write
y = x++;
then the variable y gets the value of x before its incrementing.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the operand.
As a side effect, the value of the operand object is incremented (that
is, the value 1 of the appropriate type is added to it). ... The
value computation of the result is sequenced before the side effect of
updating the stored value of the operand. ...
If instead of the expression
c = (*p)++;
you'll write
c = ++(*p);
then you get the expected by you result. This demonstrates the difference between the postfix increment operator ++ and the prefix (unary) increment operator ++.
When the ++ is following a variable, the variable is incremented after it has been used.
So when you have
y = x++;
x is incremented after y gets the value of x.
This is how it works for the -- operator also.
This question already has answers here:
Pointer expressions: *ptr++, *++ptr and ++*ptr
(11 answers)
Closed 5 years ago.
If we have
int i = 5; /*line 1*/
int *p = &i; /*line 2*/
*p++; /*line 3*/
What is the order of evaluation for line 3?
(I know that after this p might point to something weird - but I'm not interested in the correct memory addressing but the order of evaluation, as both * and ++ seems to have same precedence)
No, postfix increment has higher precedence.
In your case, the side-effect of the increment will take place after the value evaluation note (with the dereference operator). The result of the value evaluation, though, is discarded (you did not make any effort to store the result).
So, finally, the result will be the equivalent as p++;
Note:
Quoting C11, chapter §6.5.2.4, (emphasis mine)
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented (that is, the value 1 of the appropriate type is
added to it). See the discussions of additive operators and compound assignment for
information on constraints, types, and conversions and the effects of operations on
pointers. The value computation of the result is sequenced before the side effect of
updating the stored value of the operand. [...]
*p++ is treated as *(p++) because precedence of postfix ++ is higher than *.
You have to put parenthesis around the *p for this to work:
int i = 5; /*line 1*/
int *p = &i; /*line 2*/
(*p)++; /*line 3*/
printf("Hello, World! %d\n", *p);
See: http://en.cppreference.com/w/c/language/operator_precedence
int main()
{
int a=10;
int *b=&a;
int c=*b++;
printf("%d",c);
}
I know following program outputs 10.but according to precedence table which gives precedence of operator http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm) ,post-fix ++ has higher precedence than = and *.so ++ should evaluate first and then *.then why program is printing output as 10?
It does have higher precedence, which means the pointer will get increased by one, not the value it points to.
But the increase by one is sequenced to the end of the evaluation( that is what postfix ++ does, and that is not directly related to precedence ), so the value you get out of the pointer is the old one: p not p+1. Having that pointer, you dereference it and get the value of a, which is 10. Then the pointer p is incremented by one.
int c = *p ;
p++ ;
The ++ will do an increment of b, a memory address, after evaluation in the context of the larger expression.
From http://msdn.microsoft.com/en-us/library/e1e3921c.aspx:
It is important to note that a postfix increment or decrement expression evaluates to the value of the expression prior to application of the respective operator. The increment or decrement operation occurs after the operand is evaluated. This issue arises only when the postfix increment or decrement operation occurs in the context of a larger expression.
So, what happens is that you apply a post-fix increment to b, but the dereference * is given the original value of b, which points to 10. If you were to print out b or *b you'll see that the value and address have changed to something unexpected.
As you say, ++ has higher precedence than *. So int c=*b++; parses as int c=*(b++);. However, the result of the post-increment operator is the value before incrementing. In other words, the assignment is equivalent to
int temp = b;
b = b + 1;
c = *temp;
++ has higher precedence than * means operand b will bind to ++ first as
int c = *(b++);
It doesn't mean in any way that evaluate b++ first and then dereference the evaluated value.
In *b++, ++ will have the same effect on b as that post increment operator do. *b++ is simply: Dereference original value of b and increment the pointer b by 1.
Yes, ++ has higher precedence than *.
So, the statement
int c=*b++;
will be evaluated as
int c=*(b++)
Since it's post-fix operator, the pointer 'b' is incremented first, but it returns the old address of 'b'(which points to address storing the value 10 ).
Therefore, c will have the value 10.