Why doesn't this program print '4'? [duplicate] - c

This question already has answers here:
Post-increment on a dereferenced pointer?
(13 answers)
Closed 3 years ago.
Shouldn't ptrj value be 4 after the execution of *ptrj++?
int j=3,*ptrj = NULL;
ptrj = &j;
*ptrj++;
printf("%i",*ptrj);

*ptrj++ is the same as *(ptrj++). What you expect is instead (*ptrj)++. You should look up operator precedence to learn more about which operators that acts before others. To understand what ptrj++ does, you should read about pointer arithmetic. But here is a quick explanation:
*(ptrj++) returns the value that ptrj points to (3), and THEN increments ptrj to point to the next value.
(*ptrj)++ returns the value that ptrj points to (3), and THEN increments the value that ptrj points at from 3 to 4.
This means that what you're printing is the value at address &j + 1, which is the value that lies right after the variable j in memory. and this is undefined behavior. As Sourav pointed out, you would get a warning that points you to this if you enable compiler warnings.
The only difference between *ptrj++ and ptrj++ is what it is returning. And since you don't use the return value, your code is equivalent to:
int j=3,*ptrj = NULL;
ptrj = &j;
ptrj++;
printf("%i",*ptrj);

If you compile the program with warnings enabled, you'll see
source_file.c:9:5: warning: value computed is not used [-Wunused-value]
*ptrj++;
^
That means, the value computation is useless.
In other words, according to the operator precedence *ptrj++; is same as *(ptrj++);, and as per the post-increment operator property, the value of the operation is the value of the operand, and the value is increased as the side-effect.
Quoting C11, chapter
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). [....]
So, this is same as
*ptr;
ptr++;
If you want to increment that value at the address, you need to enforce the operator precedence by using explicit parenthesis, like
(*ptrj)++; // first get the value, then update the value.

*ptrj++ is equivalent to *(ptrj++).
desired output can be achieved using (*ptrj)++.
Please refer https://www.geeksforgeeks.org/c-operator-precedence-associativity/ to get how operator works.

Precedence of postfix ++ is higher than *. The expression *ptrj++ is treated as *(ptrj++) as the precedence of postfix ++ is higher than *.If you want to print 4 ( ie ptrj+1 ),You should use the following code:-
int j=3,*ptrj = NULL;
ptrj = &j;
(*ptrj)++;
printf("%i",*ptrj);
return 0;
To know more about operator precedence, refer follow link:
https://en.cppreference.com/w/c/language/operator_precedence

Related

Priority operators in C

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.

What happens when you dereference a postincrement C

I am receiving a lot of conflicting answers about this. But as I always understood it.
When we have a pointer in C and use it in a post increment statement, the post increment will always happen after the line of code resolves.
int array[6] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *p++); // This will output 0 then increment pointer to 1
output :
0
Very simple stuff. Now here's where I am receiving a bit of dissonance in the information people are telling me and my own experience.
// Same code as Before
int array[0] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *(p++)); // Issue with this line
output :
0
Now when I run that second version of the code The result is that it will output 0 THEN increments the pointer. The order of operations implied by the parentheses seems to be violated. However some other answers on this site tell me that the proper thing that should happen is that the increment should happen before the dereference. So I guess my question is this: Is my understanding correct? Do post increment statements always execute at the end of the line?
Additional Info:
I am compiling with gcc on linux mint with gcc version ubuntu 4.8.4
I have also tested this on gcc on debian with version debian 4.7.2
OP's "The result is that it will output 0 THEN increments the pointer." is not correct.
The postfix increment returns the value of the pointer. Consider this value as a copy of the original pointer's value. The pointer is incremented which does not affect the copy.
The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented. ... C11dr 6.5.2.4 2
Then the copy of the pointer is de-referenced and returns the 0. That is the functional sequence of events.
Since the side-effect of incrementing the pointer and de-referencing that copy of the pointer do not effect each other, which one occurs first is irrelevant. The compiler may optimized as it likes.
"the end of the line" is not involved in code. It is the end of the expression that is important.
There is no difference in meaning between *p++ and *(p++).
This is because postfix operators have a higher precedence than unary operators.
Both these expressions mean "p is incremented, and its previous value is dereferenced".
If you want to increment the object being referenced by the pointer, then you need to override precedence by writing (*p)++.
No version of your code can produce output and then increment p. The reason is that p is incremented in an argument expression which produces a value that is passed into printf. In C, a sequence point occurs just before a function is called. So the new value of p must settle in place before printf executes. And the output cannot take place until printf is called.
Now, you have to take the above with a slight grain of salt. Since p is a local variable, modifying it isn't an externally visible effect. If the new value of p isn't used anywhere, the increment can be entirely optimized away. But suppose we had an int * volatile p; at file scope, and used that instead. Then the expression printf("...", *p++) has to increment p before printf is called.
The expression p++ has a result (the value of p before the increment) and a side effect (the value of p is updated to point to the next object of type int).
Postfix ++ has higher precedence than unary *, so *p++ is already parsed as *(p++); you will see no difference in behavior between those two forms. IOW, the dereference operator is applied to the result of p++; the line
printf("%d", *p++);
is roughly equivalent to
printf("%d", *p);
p++;
with the caveat that p will actually be updated before the call to printf1.
However, (*p)++ will be different; instead of incrementing the pointer, you are incrementing the thing p points to.
1. The side effect of a ++ or -- operator must be applied before the next sequence point, which in this particular case occurs between the time the function arguments are evaluated and the function itself is called.
Here is my take on this. Let's ignore the printf function altogether and make things simpler.
If we said
int i;
int p=0;
i = p++;
Then i would be equal to zero because p was equal to zero but now p has been incremented by one; so now i still equals zero and p is equal to 1.
Ignoring the declarations of i and p as integers, if we wrap this as in the example, i = *(p++), then the same action occurs but i now contains the value pointed at by p which had the value of zero. However, the value of p, now, has been incremented by one.

Confused with pre and post increment operator [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
hello I am learning basics of C programming language, recently i have studied about post and pre increment/decrement operators and also about lvalue and rvalue, the following program shows an error, lvalue required, according to me it should give a value of 6, Can anyone please explain why?
int main(){
int x = 8, y;
y = --x--;
printf("y=%d",y);
return 0;
}
Please explain, why is it so?
Well, let's see what is happening in --x--.
At first, post-decrement executes: --(x--).
(x--) = 7.
After that result of this operation is placed to the original structure:
--7 - doesn't make sense - thus you get lvalue required error
The statement y = --x--; will give you the following error on compilation in C. lvalue required. This is because the post decrement operator -- will return an rvalue after operating on the variable x. So there are no lvalue to perform the pre decrement operator -- afterwards.
But this is one point where C and C++ differs. In C the following statement will also give you the same error lvalue required.
y = (--x)--;
But in C++ the statement y = (--x)--; will compile fine and the value of y is 7. Because unlike C, C++ returns an lvalue after performing the pre decrement operator on variable x.
L Value is left operand of assignment operator which should refer to memory location.As explained by #Pavel your Lvalue is becoming a value not object so you are getting error.
--x means x = x-1 but in your case it is becoming --7 which will be equivalent to 7 =7-1 which is definitely not valid expression.
Other than this more than one operation on same variable without any sequence point in between, results undefined behaviour.
C order of operations specifies that postfix operators have precedence over the prefix operators. The -- postfix operator returns the current value (an rvalue) of the operand and then decrements the operand. Then the prefix decrement operator would be applied...but the decrement/increment operators need lvalue operands since they by definition modify their operands. So, as the compiler says, an lvalue is required.
You should not use it at a time because you will not understand the behavior of compiler. So, you need to guide your code so that they will forced to do what you like.
Now come to your point. If you want to decrease the value by one you can use a-- or --a. They will do the same. If a = 5 and you use b=a-- you will get b = 5 and a = 4 where if you use b=--a you will get b = 4 and a = 4 in --a the value is assigned immediately and in a-- value will be assigned after statement is complete. Hope you are clear.
L value required error shown when it doesn't find any suitable variable where it can be assigned.

Confusing answers : One says *myptr++ increments pointer first,other says *p++ dereferences old pointer value

I would appreciate if you clarify this for me.Here are two recent questions with their accepted answers:
1) What is the difference between *myptr++ and *(myptr++) in C
2) Yet another sequence point query: how does *p++ = getchar() work?
The accepted answer for the first question,concise and easily to understand states that since ++ has higher precedence than *, the increment to the pointer myptr is done first and then it is dereferenced.I even checked that out on the compiler and verified it.
But the accepted answer to the second question posted minutes before has left me confused.
It says in clear terms that in *p++ strictly the old address of p is dereferenced. I have little reason to question the correctness of a top-rated answer of the second question, but frankly I feel it contradicts the first question's answer by user H2CO3.So can anyone explain in plain and simple English what the second question's answer mean and how come *p++ dereferences the old value of p in the second question.Isn't p supposed to be incremented first as ++ has higher precedence?How on earth can the older address be dereferenced in *p++Thanks.
The postfix increment operator does have higher precedence than the dereference operator, but postfix increment on a variable returns the value of that variable prior to incrementing.
*myptr++
Thus the increment operation has higher precedence, but the dereferencing is done on the value returned by the increment, which is the previous value of myptr.
The answer in the first question you've linked to is not wrong, he's answering a different question.
There is no difference between *myptr++ and *(myptr++) because in both cases the increment is done first, and then the previous value of myptr is dereferenced.
The accepted answer for the first question,concise and easily to understand states that since ++ has higher precedence than *,
Right. That is correct.
the increment to the pointer myptr is done first and then it is dereferenced.
It doesn't say that. Precedence determines the grouping of the subexpressions, but not the order of evaluation.
That the precedence of ++ is higher than the precedence of the indirection * says that
*myptr++
is exactly the same (not on the cource code level, of course) as
*(myptr++)
and that means that the indirection is applied to the result of the
myptr++
subexpression, the old value of myptr, whereas (*myptr)++ would apply the increment operator to what myptr points to.
The result of a postfix increment is the old value of the operand, so
*myptr++ = something;
has the same effect as
*myptr = something;
myptr++;
When the side-effect of storing the incremented value of myptr happens is unspecified. It may happen before the indirection is evaluated, or after that, that is up to the compiler.
Section 6.5.2.4 of the C specification discusses the postfix increment and decrement operators. And the second paragraph there pretty much answers your question:
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.
So given *myptr++, yes it's true the the ++ part has higher precedence; but precedence does not exclusively determine your result. The language defines that with the specs. In this case the value of myptr is returned, then the "side effect" of myptr being incremented is executed.

Does *p++ increment after dereferencing? [duplicate]

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

Resources