sequence point and side effects - c

According to sequence point definition, sequence points are "specified points in the execution sequence called sequence points, all side effects of previous evaluations are guaranteed to be complete"
So in the below program, all side effects of ++ operator must have been performed before going to second part of && operator, i.e, i should be incremented to 1 as && is a sequence point.
#include<stdio.h>
int main()
{
int i=0,a;
a=i++&&1;
printf("%d",a);
getchar();
return 0;
}
Expected output:
1 (1&&1=1)
actual output :
0
Why doesn't i increment before 2nd part?
Using the ternary operator also gives same output:
#include<stdio.h>
int main()
{
int i=0,a;
a=(i++)?1:0;
printf("%d",a);
getchar();
return 0;
}
The ternary operator is also a sequence point. So shouldn't this give output 1 instead of 0?

i++
Evaluates to previous value of i.
As a side effect value of i is incremented by 1.
So yes the sequence point is there but the expression i++ evaluates to 0 (though value of i is 1 at the same time)
For the expected results use ++i instead of i++.
From 6.5.2.4 Postfix increment and decrement operators in C11 specs:
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.98)
98) Where a pointer to an atomic object can be formed and E has
integer type, E++ is equivalent to the following code sequence where T
is the type of E:
T *addr = &E;
T old = *addr;
T new;
do {
new = old + 1;
} while (!atomic_compare_exchange_strong(addr, &old, new));
with old being the result of the operation. Special care must be taken
if E has floating type; see 6.5.16.2.)

Related

Will this expression evaluate to true or false (1 or 0) in C?

#include<stdio.h>
int main()
{
int a=4;
int b=4;
int c= a++ < ++b? 1 : 0;
printf ("%d",c);
}
It is known that there is a sequence point at ?, which means that both the prefix and postfix operations have to be completed by that point. Also it is known(?) that b is incremented before the comparison. However, is a incremented before or after the comparison?
If it is incremented before the < test, then the Boolean evaluates to false and c is set to 0, else to true with c being set to 1. In my compiler, it evaluates to true, which means a++ is performed after the comparison operation with c being set to 1.
Is this behavior part of the specification though?
I modified it to
#include<stdio.h>
int main()
{
int a=4;
int b=4;
int d=2;
int c= a++ + d < ++b + d? 1 : 0;
printf ("%d",c);
}
and it still evaluates to 1. The postfix has to complete before the ?, but does that really ensure that it happens after the comparison < ?
a++ returns the value of a before the increment. ++b returns the value of b after the increment. Thus this evaluates to 1.
As neither a nor b are used more than once in the expression, no undefined behavior exists.
Also it is known(?) that b is incremented before the comparison.
However, is a incremented before or after the comparison?
This is a subtle point, but it's important to understand what's really going on here.
Both the subexpressions a++ and ++b do two things. They compute a new value to be used in the surrounding expression, and they update the stored value of the variable they're operating on.
So a++ does this:
it yields the old value of a (4) out to the surrounding expression
it stores a new value (5) into a.
And ++b does this:
it yields the new value of b (4+1 or 5) out to the surrounding expression
it stores a new value (5) into b.
Notice that in both cases it's thing 1 that the < operator cares about. And, in both cases, thing 1 is an absolute definition, it doesn't depend on timing.
Or, in other words, asking "Is a/b incremented before or after the comparison?" is not really the right question. The values a and b+1 participate in the comparison, and that's it.
Where the timing comes in is things 2. We don't know, precisely, when the new value gets stored back into a. Nor do we know precisely when the new value gets stored back into b. All we know is that those stores will happen sometime before the next sequence point (which, as you correctly note, in this case is the ? part of the ternary operator).
But nothing depends on those timings, so there's no undefined behavior here.
Undefined behavior comes in when either
the variable that's modified (a or b) also has its value independently used elsewhere in the expression, meaning that we don't know whether that use uses the old or the new value
the same variable is modified twice, meaning that we don't know which of the two modifications "wins"
But, again, neither of those problems occurs here, so the expression is well-defined.
This is what C11 says about the two:
Postfix ++:
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.
Prefix ++:
The value of the operand of the prefix ++ operator is incremented. The
result is the new value of the operand after incrementation. The
expression ++E is equivalent to (E+=1).
Aside:
int c= a++ < ++b? 1 : 0;
The operator < returns either 1 or 0, or true or false. So the above statement can also be written as:
int c = a++ < ++b;
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).
So in this declaration
int c= a++ < ++b? 1 : 0;
the value of the sub-expression a++ used in the initializer is the value of the operand a before its increment.
On the other hand (The C Standard (6.5.3.1 Prefix increment and decrement operators) )
2 The value of the operand of the prefix ++ operator is incremented.
The result is the new value of the operand after incrementation.
So the value of the sub-expression ++b is the value after incrementing b.
Hence you have in fact
int c = 4 < 5 ? 1 : 0;
As for the sequence point then to demonstrate it you could write for example
int c = a++ < b++ ? a : b;
In this case the variable c will have the value of the variable b after applying to it the side effect of incrementing that is to 5.

C Operator Precedence postfix increment and dereference

Here is another naïve question from a C newbie: on this page, https://en.cppreference.com/w/c/language/operator_precedence, the precedence of the postfix increment is listed to be higher than that of pointer dereference. So I was expecting in the following code that the pointer is incremented first (pointing at 10) and then dereferenced.
#include <stdio.h>
int main()
{
int a[] = {3, 10, 200};
int *p = a;
printf("%d", *p++);
return 0;
}
However this code outputs still the first array item (3). What am I missing by the concept?
Precedence is placing of parenthesis.
The expression *p++ can be parenthesized as
(*p)++ // incorrect precedence
*(p++) // correct precedence
Note that the value of p++ is the value of p before any change, so the net effect of the correct precedence is the same as *p without ant reflection over the side-effect ++. The change to p itself does not alter the result of *(p++).
As you have correctly assumed, the expression *p++ is evaluated as *(p++); that is, the ++ operator has higher precedence than the * operator.
However, the value of the expression, p++, is just the value of p (i.e. its value before the increment). A side-effect of the operation is that the value of p is incremented after its value has been acquired.
From this Draft C11 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. With
respect to an indeterminately-sequenced function call, the operation of
postfix ++ is a single evaluation. …
Operator precedence specifies how an expression is parsed. Since postfix ++ has higher precedence than *, the expression is equivalent to *(p++). Rather than (*p)++ which would have given it a completely different meaning.
But just because this forces p++ to be evaluated first, it doesn't affect the characteristic of the ++ operator. The C language specifies this operator to behave as (from C17 6.5.2.4/2):
"The value computation of the result is sequenced before the side effect of
updating the stored value of the operand."
This means that p++ always gives the value of p before ++ is applied. In this case p is a pointer, so the value will be the address it pointed at prior this expression. So the code is completely equivalent to this:
int* tmp = p;
p++;
printf("%d", *tmp);
Precedence controls which operators are grouped with which operands. Postfix ++ having higher precedence than unary * simply means that *p++ is parsed as *(p++) instead of (*p)++.
*(p++) means you are dereferencing the result of p++. The result of p++ is the current value of p. As a side effect p is incremented. It is logically equivalent to
tmp = p;
printf( "%d\n", *tmp );
p = p + 1;
where the printf call and the update to p can happen in any order, even simultaneously (interleaved or in parallel).

Order of Evaluation in C Operators

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.

How is the increment operator evaluated in C programs?

I have two expressions:
int a=5;
int c=++a;// c=6, a=6
int b=a++;// b=6, a=7
In the second instruction, the increment is evaluated first and in the third instruction, the increment is evaluated after the assignment.
I know that the increment operator has a higher priority. Can anyone explain to me why it's evaluated after assignment in the third expression?
The result is not related to the order of operations but to the definition of prefix ++ and postfix ++.
The expression ++a evaluates to the incremented value of a. In contrast, the expression a++ evaluates to the current value of a, and a is incremented as a side effect.
Section 6.5.2.4p2 of the C standard says the following about postfix ++:
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).
And section 6.5.3.1p2 says the following about prefix ++:
The value of the operand of the prefix ++ operator is incremented. The
result is the new value of the operand after incrementation. The
expression ++E is equivalent to (E+=1)
++a and a++ are simply different operators, despite the same symbol ++. One is prefix-increment, one is postfix-increment. This has nothing to do with priority compared to assignment. (just like a - b and -a are different operators despite the same symbol -.)
EDIT: It was pointed out that this is about C and not C++... oops. So, the following explanation may be confusing if you only know C; all you need to know is that int& is a reference to an int, so it's like having a pointer but without the need to dereference it, so modifying a inside of these functions actually modifies the variable you passed into the functions.
You could imagine them like functions:
int prefixIncrement(int& a) {
return ++a;
}
...is the same as:
int prefixIncrement(int& a) {
a += 1;
return a;
}
And:
int postfixIncrement(int& a) {
return a++;
}
...is the same as:
int postfixIncrement(int& a) {
int old = a;
a += 1;
return old;
}
For nitpickers: Yes, actually we'd need move semantics on the return value for postfixIncrement.

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.

Resources