Is the output of printf ("%d %d", c++, c); also undefined? - c

I recently came across a post What is the correct answer for cout << c++ << c;? and was wondering whether the output of
int c = 0;
printf ("%d %d", c++, c);
is also undefined??
I have studied in lectures that post-fix and prefix operators increment value only after getting a semicolon. So according to me, the output 0 0 is correct !!!

I have studied in lectures that post-fix and prefix operators increment value only after getting a semicolon.
Send your lecturer to me so that I can take a baseball bat to him politely point out his mistake.
Exactly when the side effect of either pre- or postfix ++ and -- is applied is unspecified, apart from the requirement that it happen before the next sequence point. In an expression like
x = a++ * b
a may be updated immediately after a++ has been evaluated, or the update may be deferred until a++ * b has been evaluated and the result assigned to x, or anywhere in between.
This is why expressions like i++ * i++ and printf("%d %d", c++, c) and a[i++] = i and a host of others are all bad juju. You will get different results based on the compiler, optimization settings, surrounding code, etc. The language standard explicitly leaves the behavior undefined so that the compiler is under no obligation to "do the right thing", whatever the right thing may be. Remember, the definition for undefined behavior is
3.4.3
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
results, to behaving during translation or program execution in a documented manner characteristic of the
environment (with or without the issuance of a diagnostic message), to terminating a translation or
execution (with the issuance of a diagnostic message).
3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.
This is a deliberate design decision - the rationale for leaving the order of these operations unspecified is to give the implementation freedom to rearrange the evaluation order for optimization purposes. However, in exchange for this freedom, certain operations will not have well-defined results.
Note that a compiler is free to try to detect these cases and issue a diagnostic; printf("%d %d", c++, c); would be easy enough to catch, but this would be a bugger to detect in the general case. Imagine if that had been written printf("%d %d", (*p)++, c); if p points to c, then the behavior is undefined, otherwise it's okay. If p is assigned in a different translation unit, then there's no way to know at compile time whether this is a problem or not.
This concept is not difficult to understand, yet it is one of the most consistently misunderstood (and mis-taught) aspects of the C language. No doubt this is why the Java and C# language specifications force a specific evaluation order for everything (all operands are evaluated left-to-right, and all side effects are applied immediately).

I have studied in lectures that post-fix and prefix operators increment value only after getting a semicolon
This is not how the standard describes it. A sequence point is a point in code in which side effects which may have occurred in previous parts of the code have been evaluated. The comma between arguments to a function is not a sequence point, so the behavior there is undefined.
The evaluation order of function arguments is unspecified. There is no guarantee that the arguments to a function will be evaluated in the order (1, 2, N), so there is no guarantee that the increment will be evaluated before the second argument is passed.
So according to me, the output 0 0 is correct !!!
No, the behavior is undefined, so you cannot reasonably claim that the output will be 0 0.

The behavior of the program is undefined because it has violated the requirements of 6.5 Expressions:
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
c++ and c are both evaluated without an intervening sequence point, and the prior value of c is read both to determine the value to be stored by c++, and to determine the value of the expression c.

The behaviour will be definitely undefined due to the undefined evaluation order of parameters. You can prove this "undefined output" doing some random testing:
printf("%d %d\n", c++, c);
// result: 0 1
printf("%d %d %d\n", c++, c, c++);
// result: 1 2 0
printf("%d %d %d %d\n", c++, c++, c++, c);
// result: 2 1 0 3
printf("%d %d %d %d\n", c++, c, c++, c);
// result: 1 2 0 2
printf("%d %d %d %d\n", c++, c, c, c);
// result: 0 1 1 1

You are right: it is undefined. The reason is that, though it is guaranteed that the three arguments to printf() will be evaluated before printf() is called, the sequence in which the three arguments are evaluated is undefined.
It is technically incorrect that the incrementation occurs only after the semicolon, incidentally. What the standard guarantees is that the incrementation will occur no later than the semicolon. [Actually, in your case, I believe that the standard guarantees that it will occur before control is passed to the printf() function -- but now this answer is starting to spin off into realms of pedantic trivia, so let me let the matter rest there!]
Anyway, in short, you are right. The behavior is undefined.
Update: As #R.. rightly observes, the undefined behavior comes from the lack of a sequence point between arguments. The standard is quite careful regarding the participles unspecified and undefined, so the correction is accepted with thanks.

This program exhibits a combination of both unspecified behavior and undefined behavior. Starting with the unspecified behavior, the draft C99 standard in section6.5 paragraph 3 says:
The grouping of operators and operands is indicated by the syntax.74)
Except as specified later (for the function-call (), &&, ||, ?:, and
comma operators), the order of evaluation of subexpressions and the
order in which side effects take place are both unspecified.
It also says except as specified later and specifically cites function-call (), so we see that later on the draft standard in section 6.5.2.2 Function calls paragraph 10 says:
The order of evaluation of the function designator, the actual
arguments, and subexpressions within the actual arguments is
unspecified, but there is a sequence point before the actual call.
So we do not know whether the read of C or the evaluation of C++ will happen first at this line of code:
printf ("%d %d", c++, c);
furthermore, in section 6.5.2.4 Postfix increment and decrement operators paragraph 2 says:
[...] After the result is obtained, the value of the operand is incremented. [...] The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.
So all we know is that when performing the post increment c will be updated after its value is read but before the next sequence point which is right before printf is called but nothing else. As for the undefined behavior, if we look at section 6.5 paragraph 2 from the draft standard, is says:
Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore, the prior value
shall be read only to determine the value to be stored.
In the printf expression cs prior value is being read in order to evaluate both C++ and C and so we now are in undefined territory.

Related

Is this a C language undefined behaviour? Different results in clang and GCC

I'm getting different results for the same code with different compilers. Is this a undefined behaivour?
#include <stdio.h>
int a;
int b=10;
int puan_ekle(int puan, int bonus){
puan=puan+bonus;
a=puan-5;
bonus--;
return bonus;
}
int main(){
a=23;
printf("Result1 %d \n", a);
a=a+puan_ekle(a,b);
printf("Result2 %d \n", a);
a=a+puan_ekle(a,b);
printf("Result3 %d \n", a);
}
The behavior is unspecified, not undefined.
The C standard distinguishes these. C 2018 3.4.4 1 says:
unspecified behavior
behavior, that results from the use of an unspecified value, or other behavior upon which this document provides two or more possibilities and imposes no further requirements on which is chosen in any instance
And 3.4.3 1 says:
undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this document imposes no requirements
In some situations, when an object is both used for its value and modified, a rule in the C standard makes the behavior undefined. 6.5 2 says:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
Let’s see how this applies to a=a+puan_ekle(a,b);. In this expression:
a is modified by the a=.
a is used in the a+.
a is used in the arguments (a,b).
Inside the function puan_ekle, a is modified with a=puan-5;.
The modifications are side effects—they are something that happens separately from computing the value of the expression. If either of the modifications, 1 or 4, is unsequenced relative to any of the other items, the behavior is undefined.
Regarding 1, 6.5.16 3 says:
… The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands…
So 1 is sequenced after 2 and 3. Since 4 is a side effect, not a value computation, we still have to consider the relationship of 1 and 4. To resolve this, we will consider sequence points. Per 5.1.2.3, “The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.”
Next we need to know what a full expression is and that there is a sequence point after each full expression. 6.8 4 says:
A full expression is an expression that is not part of another expression, nor part of a declarator or abstract declarator… There is a sequence point between the evaluation of a full expression and the evaluation of the next full expression to be evaluated.
This means that every statement inside puan_ekle is or contains a full expression: puan=puan+bonus is a full expression, a=puan-5 is a full expression, bonus-- is a full expression, and the bonus in return bonus is a full expression. So, after a=puan-5, there is a sequence point.
Since, for a=, the side effect of modifying a is sequenced after the value computations of the operands. Evaluating those operands includes calling the function, which includes its sequence points. So effect 4, modifying a in a=puan-5;, must be completed before execution continues to the next statement, and hence must be completed before effect 1. So 1 and 4 are sequenced.
What is left is to consider effect 4 with respect to 2 and 3. 4 is sequenced after 3 because a function call is sequenced after evaluation of its arguments, per 6.5.2.2 10:
There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call…
Now all we have left is the sequencing of 2 relative to 4. In this, there is no specification of which is first. The evaluations of the operands of + are unsequenced, so, for a+puan_ekle(a,b), a C implementation may do either a first or puan_ekle(a,b) first. However, whichever it does first, there is a sequence point between 2 and 4:
If a is evaluated first, then, before the function call, there is a sequence point (per 6.5.2.2 10, quoted above).
If puan_ekle(a,b) is evaluated first, there is a sequence point after the full expression a=puan-5.
Thus, 2 and 4 are indeterminately sequenced. (5.1.2.3 3: “… Evaluations A and B are indeterminately sequenced when A is sequenced either before or after B, but it is unspecified which…”) But they are not unsequenced, so there is no undefined behavior. The behavior is unspecified because there are two possibilities. The C implementation is required implement one of those two possibilities, which is different from undefined behavior, in which there would be no requirements.
The order pf evaluation of the operands of an additive operator is unspecified.
So for example in this statement
a=a+puan_ekle(a,b);
one compiler can at first evaluate the value of a and then call the function puan_ekle(a,b) that has a side effect of changing a. While other compiler can at first call the function and after that get the value of a after it was changed in the function.
So the program has undefined behavior.
If the function had no the side effect then the behavior would be well-defined independently of the order of evaluation of operands of the additive operator.

What would happen if "i = i++" was not considered undefined behavior? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I'm having trouble understanding the difference between unspecified and undefined behavior. I think trying to understand some examples would be useful. For instance, x = x++. The problem with this assignment is that:
Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
This violates a shall rule, but does not explicitly invoke undefined behavior, but it involves UB according to:
The order of evaluation of the operands is unspecified. If an attempt is made to modify the result of an assignment operator or to access it after the next sequence point, the behavior is undefined.
Assuming none of these rules existed and there are no other rules that "invalidate" x = x++. The value of x would then be unspecified, right?
The doubt arised because sometimes it is argued that things in C are UB by "default" are only valid you can justify that the construction is valid.
Edit: As pointed out by P.W, there is a somewhat related, well-received, version of this question for C++: What made i = i++ + 1; legal in C++17?.
I'm having trouble understanding the difference between unspecified and undefined behavior.
Then let's start with the definitions of those terms from the Standard:
undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this
International Standard imposes no requirements
NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during
translation or program execution in a documented manner characteristic
of the environment (with or without the issuance of a diagnostic
message), to terminating a translation or execution (with the issuance
of a diagnostic message).
EXAMPLE An example of undefined behavior is the behavior on integer overflow.
(C2011, 3.4.3)
unspecified behavior use of an unspecified value, or other behavior where this International Standard provides two or more
possibilities and imposes no further requirements on which is chosen
in any instance
EXAMPLE An example of unspecified behavior is the order in which the
arguments to a function are evaluated.
(C2011, 3.4.4)
You remark that
The doubt arised because sometimes it is argued that things in C are
UB by "default" are only valid you can justify that the construction
is valid.
It is perhaps over-aggrandizing that to call it an argument, as if there were some doubt about its validity. In truth, it reflects explicit language from the standard:
If a ''shall'' or ''shall not'' requirement that appears outside of a
constraint or runtime- constraint is violated, the behavior is
undefined. Undefined behavior is otherwise indicated in this
International Standard by the words ''undefined behavior'' or by the
omission of any explicit definition of behavior. There is no
difference in emphasis among these three; they all describe ''behavior
that is undefined''.
(C2011, 4/2; emphasis added)
When you posit
Assuming none of these rules existed and there are no other rules that
"invalidate" x = x++.
, that doesn't necessarily change anything. In particular, removing the explicit rule that the order of evaluation of the operands is unspecified does not make the order specified. I'd be inclined to argue that the order remains unspecified, but the alternative is that the behavior would be undefined. The primary purpose served by explicitly saying it's unspecified is to sidestep that question.
The rule explicitly declaring UB when an object is modified twice between sequence points is a little less clear, but falls in the same boat. One could argue that the standard still did not define behavior for your example case, leaving it undefined. I think that's a bit more of a stretch, but that's exactly why it is useful to have an explicit rule, one way or the other. It would be possible to define behavior for your case -- Java does, for example -- but C chooses not to do, for a variety of technical and historical reasons.
The value of x would then be unspecified, right?
That's not entirely clear.
Please understand, too, that the various provisions of the standard for the most part do not stand alone. They are designed to work together, as a (mostly) coherent whole. Removing or altering random provisions has considerable risk of producing inconsistencies or gaps, leaving it difficult to reason about the result.
Modern C11/C17 has changed the text, but it has pretty much the same meaning. C17 6.5/2:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar
object, the behavior is undefined.
There are several slightly different issues here, mixed into one:
Between sequence points, x is written to (side effect) more than once. This is UB as per the above.
Between sequence points, the expression contains at least one side effect and there is a value computation of the same variable not related to which value to be stored. This is also UB as per the above.
In the expression x = x++, the evaluation of the operand x is not sequenced in relation to the operand x++. The evaluation order is unspecified behavior as per C17 6.5.16.
The side effect of updating the stored value of the left operand is
sequenced after the value computations of the left and right operands. The evaluations of
the operands are unsequenced.
If not for the first cited part labelling this UB, then we still wouldn't know if the x++ would be sequenced before or after the evaluation of the left x operand, so it is hard to reason about how this could become "just unspecified behavior".
C++17 actually fixed this part, making it well-defined there, unlike in C or earlier C++ versions. They did so by defining the sequence order (C++17 8.5.18):
In all cases, the assignment is sequenced after the value
computation of the right and left operands, and before the value computation of the assignment expression.
The right operand is sequenced before the left operand.
I don't see how there can be any middle-ground here; either the expression is undefined or it is well-defined.
Unspecified behavior is deterministic behavior which we cannot know or assume anything about. But unlike undefined behavior, it won't cause crashes and random program behavior.
A good example is a() + b(). We can't know which function that will be executed first - the program doesn't even have to be consistent if the same line appears later on in the same program. But we can know that both functions will be executed, one before the other.
Unlike x = a() + b() + x++; which is undefined behavior and we can't assume anything about it. One, both or none of the functions might be executed, in any order. The program might crash, produce incorrect results, produce seemingly correct results or do nothing at all.
There have been instances in other programming languages when a previously undefined behavior has become defined in a later standard. One instance I can remember is in C++ where what was undefined behavior in C++11 became well defined in C++17.
i = i++ + 1; // the behavior is undefined in C++11
i = i++ + 1; // the behavior is well-defined in C++17. The value of i is incremented
There has been a well received question on this topic.
What made this well defined is a guarantee in the C++17 standard that
The right operand is sequenced before the left operand.
So in a sense, it is upto the standards committee people to change the standard and provide strong guarantees to make it well defined.
But I do not think that something as simple as x = x++; will be made unspecified. It's will either be undefined or well-defined.
The problem seems that it cannot be properly defined what i= i++; would mean:
Interpretation 1:
int i1= i;
int i2= i1+1;
i = i2;
i = i1;
In this interpretation the value of i is retrieved and 1 is added (i2), then this i2 is saved to i but the original i in i1 is further used in the assignment (because here the ++ is interpreted to apply to the value after it has been used) and so i is unchanged.
Interpretation 2:
int i1= i;
i1= i1+1;
i= i1;
int i2= i;
i= i2;
In this interpretation the i++ is performed first (and modifies i) and now the modified i is retrieved again and used in the assignment (so i has the incremented value).
Interpretation 3:
int i1= i;
i = i1;
int i2= i1+1;
i= i2;
In this interpretation first the assignment of i to i is executed and then i is incremented.
To me, all these three interpretations are correct, and there could even be a few more interpretations, but they each do something different. Hence the standard could/did not define it and which interpretation a compiler uses is up to the compiler builder and as a result which behavior a compiler exhibits is undefined: undefined behavior.
(A compiler could even generate a jmp toTheMoon instruction or ignore the whole statement.)
The order of evaluation and application of the side effect of ++ is left unspecified - the language standard does not mandate left-to-right or right-to-left order (for arithmetic operators, anyway). Consider the well-defined expression a = b++ * ++c. The expressions a, b++, and ++c may be evaluated in any order. Similarly, the side effects to b and c may be applied immediately after evaluation, or deferred until just before the next sequence point, or anywhere in between. All that matters is that the result of b * (c+1) is computed before being assigned to a. The following is one perfectly legal evaluation:
tmp <- c + 1;
a = b * tmp;
c <- c + 1
b <- b + 1
So is this:
c <- c + 1
a <- b * c
b <- b + 1
So is this:
tmp1 <- b
b <- b + 1
tmp2 <- c + 1
a <- tmp1 * tmp2
c <- c + 1
What matters is that, no matter what order of evaluation is chosen, you will always get the same result.
x = x++ could be evaluated in either of the following ways, depending on when the side effect is applied:
Option 1 Option 2
-------- --------
tmp <- x tmp <- x
x <- x + 1 x <- tmp
x <- tmp x <- x + 1
The problem is that the two methods give different results. Other, completely different methods may be available based on the instruction set that give different results than these two.
The language standard doesn't mandate what to do when an expression gives different results depending on the order in which it is evaluated - it doesn't place any requirements on the compiler or the runtime environment to pick either option. This is what undefined means - literally, the behavior is not defined by the language specification. You will get a result, but it's not guaranteed to be consistent, or the result you would expect.
Undefined does not mean illegal. Nor does it mean your code is guaranteed to crash. It just means that the result is not predictable or guaranteed to be consistent. An implementation doesn't even have to issue a diagnostic saying "hey, dummy, this is a bad idea."
An implementation is free to define and document a behavior left undefined by the standard (such as MSVC defining fflush on input streams). A number of compilers take advantage of certain behaviors being undefined to perform some optimizations. And some compilers do issue warnings for common mistakes like x = x++.

What makes C standard so difficult to determine the sequence point? [duplicate]

What are "sequence points"?
What is the relation between undefined behaviour and sequence points?
I often use funny and convoluted expressions like a[++i] = i;, to make myself feel better. Why should I stop using them?
If you've read this, be sure to visit the follow-up question Undefined behavior and sequence points reloaded.
(Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all this would be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)
C++98 and C++03
This answer is for the older versions of the C++ standard. The C++11 and C++14 versions of the standard do not formally contain 'sequence points'; operations are 'sequenced before' or 'unsequenced' or 'indeterminately sequenced' instead. The net effect is essentially the same, but the terminology is different.
Disclaimer : Okay. This answer is a bit long. So have patience while reading it. If you already know these things, reading them again won't make you crazy.
Pre-requisites : An elementary knowledge of C++ Standard
What are Sequence Points?
The Standard says
At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations
shall be complete and no side effects of subsequent evaluations shall have taken place. (§1.9/7)
Side effects? What are side effects?
Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).
For example:
int x = y++; //where y is also an int
In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.
So far so good. Moving on to sequence points. An alternation definition of seq-points given by the comp.lang.c author Steve Summit:
Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.
What are the common sequence points listed in the C++ Standard?
Those are:
at the end of the evaluation of full expression (§1.9/16) (A full-expression is an expression that is not a subexpression of another expression.)1
Example :
int a = 5; // ; is a sequence point here
in the evaluation of each of the following expressions after the evaluation of the first expression (§1.9/18) 2
a && b (§5.14)
a || b (§5.15)
a ? b : c (§5.16)
a , b (§5.18) (here a , b is a comma operator; in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. Thus the behaviour is undefined in that case (if a is considered to be a primitive type))
at a function call (whether or not the function is inline), after the evaluation of all function arguments (if any) which
takes place before execution of any expressions or statements in the function body (§1.9/17).
1 : Note : the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically
part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument
2 : The operators indicated are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation and the operands form an argument list, without an implied sequence point between them.
What is Undefined Behaviour?
The Standard defines Undefined Behaviour in Section §1.3.12 as
behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements 3.
Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition of behavior.
3 : permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or with-
out the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
In short, undefined behaviour means anything can happen from daemons flying out of your nose to your girlfriend getting pregnant.
What is the relation between Undefined Behaviour and Sequence Points?
Before I get into that you must know the difference(s) between Undefined Behaviour, Unspecified Behaviour and Implementation Defined Behaviour.
You must also know that the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.
For example:
int x = 5, y = 6;
int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.
Another example here.
Now the Standard in §5/4 says
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
What does it mean?
Informally it means that between two sequence points a variable must not be modified more than once.
In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.
From the above sentence the following expressions invoke Undefined Behaviour:
i++ * ++i; // UB, i is modified more than once btw two SPs
i = ++i; // UB, same as above
++i = 2; // UB, same as above
i = ++i + 1; // UB, same as above
++++++i; // UB, parsed as (++(++(++i)))
i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)
But the following expressions are fine:
i = (i, ++i, 1) + 1; // well defined (AFAIK)
i = (++i, i++, i); // well defined
int j = i;
j = (++i, i++, j*i); // well defined
Furthermore, the prior value shall be accessed only to determine the value to be stored.
What does it mean? It means if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.
For example in i = i + 1 all the access of i (in L.H.S and in R.H.S) are directly involved in computation of the value to be written. So it is fine.
This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification.
Example 1:
std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2
Example 2:
a[i] = i++ // or a[++i] = i or a[i++] = ++i etc
is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. So the behaviour is undefined.
Example 3 :
int x = i + i++ ;// Similar to above
Follow up answer for C++11 here.
This is a follow up to my previous answer and contains C++11 related material..
Pre-requisites : An elementary knowledge of Relations (Mathematics).
Is it true that there are no Sequence Points in C++11?
Yes! This is very true.
Sequence Points have been replaced by Sequenced Before and Sequenced After (and Unsequenced and Indeterminately Sequenced) relations in C++11.
What exactly is this 'Sequenced before' thing?
Sequenced Before(§1.9/13) is a relation which is:
Asymmetric
Transitive
between evaluations executed by a single thread and induces a strict partial order1
Formally it means given any two evaluations(See below) A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced 2.
Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which3.
[NOTES]
1 : A strict partial order is a binary relation "<" over a set P which is asymmetric, and transitive, i.e., for all a, b, and c in P, we have that:
........(i). if a < b then ¬ (b < a) (asymmetry);
........(ii). if a < b and b < c then a < c (transitivity).
2 : The execution of unsequenced evaluations can overlap.
3 : Indeterminately sequenced evaluations cannot overlap, but either could be executed first.
What is the meaning of the word 'evaluation' in context of C++11?
In C++11, evaluation of an expression (or a sub-expression) in general includes:
value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and
initiation of side effects.
Now (§1.9/14) says:
Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.
Trivial example:
int x;
x = 10;
++x;
Value computation and side effect associated with ++x is sequenced after the value computation and side effect of x = 10;
So there must be some relation between Undefined Behaviour and the above-mentioned things, right?
Yes! Right.
In (§1.9/15) it has been mentioned that
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced4.
For example :
int main()
{
int num = 19 ;
num = (num << 3) + (num >> 3);
}
Evaluation of operands of + operator are unsequenced relative to each other.
Evaluation of operands of << and >> operators are unsequenced relative to each other.
4: In an expression that is evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.
(§1.9/15)
The value computations of the operands of an
operator are sequenced before the value computation of the result of the operator.
That means in x + y the value computation of x and y are sequenced before the value computation of (x + y).
More importantly
(§1.9/15) If a side effect on a scalar object is unsequenced relative to either
(a) another side effect on the same scalar object
or
(b) a value computation using the value of the same scalar object.
the behaviour is undefined.
Examples:
int i = 5, v[10] = { };
void f(int, int);
i = i++ * ++i; // Undefined Behaviour
i = ++i + i++; // Undefined Behaviour
i = ++i + ++i; // Undefined Behaviour
i = v[i++]; // Undefined Behaviour
i = v[++i]: // Well-defined Behavior
i = i++ + 1; // Undefined Behaviour
i = ++i + 1; // Well-defined Behaviour
++++i; // Well-defined Behaviour
f(i = -1, i = -1); // Undefined Behaviour (see below)
When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note]
Expressions (5), (7) and (8) do not invoke undefined behaviour. Check out the following answers for a more detailed explanation.
Multiple preincrement operations on a variable in C++0x
Unsequenced Value Computations
Final Note :
If you find any flaw in the post please leave a comment. Power-users (With rep >20000) please do not hesitate to edit the post for correcting typos and other mistakes.
C++17 (N4659) includes a proposal Refining Expression Evaluation Order for Idiomatic C++
which defines a stricter order of expression evaluation.
In particular, the following sentence
8.18 Assignment and compound assignment operators:....
In all cases, the assignment is sequenced after the value
computation of the right and left operands, and before the value computation of the assignment expression.
The right operand is sequenced before the left operand.
together with the following clarification
An expression X is said to be sequenced before an expression Y if every
value computation and every side effect associated with the expression X is sequenced before every value
computation and every side effect associated with the expression Y.
make several cases of previously undefined behavior valid, including the one in question:
a[++i] = i;
However several other similar cases still lead to undefined behavior.
In N4140:
i = i++ + 1; // the behavior is undefined
But in N4659
i = i++ + 1; // the value of i is incremented
i = i++ + i; // the behavior is undefined
Of course, using a C++17 compliant compiler does not necessarily mean that one should start writing such expressions.
I am guessing there is a fundamental reason for the change, it isn't merely cosmetic to make the old interpretation clearer: that reason is concurrency. Unspecified order of elaboration is merely selection of one of several possible serial orderings, this is quite different to before and after orderings, because if there is no specified ordering, concurrent evaluation is possible: not so with the old rules. For example in:
f (a,b)
previously either a then b, or, b then a. Now, a and b can be evaluated with instructions interleaved or even on different cores.
In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the following steteents are made regarding order of evaluaiton.
[...]the order of evaluation of subexpressions and the order in which
side effects take place are both unspecified. (Section 6.5 pp 67)
The order of evaluation of the operands is unspecified. If an attempt
is made to modify the result of an assignment operator or to access it
after the next sequence point, the behavior[sic] is undefined.(Section
6.5.16 pp 91)

How does an equal to expression work in a printf placeholder? [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 5 years ago.
I have the following code snippet:
main( )
{
int k = 35 ;
printf ( "\n%d %d %d", k == 35, k = 50, k > 40 ) ;
}
which produces the following output
0 50 0
I'm not sure I understand how the first value of the printf comes to 0. When the value of k is compared with 35, it should ideally return (and thus print) 1, but how is it printing zero? The other two values that are produced- 50 and 0 are all right, because in the second value, the value of k is taken as 50, and for the third value- the value of k(which is 35) is compared with 40. Since 35 < 40, so it prints 0.
Any help would be appreciated, thanks.
**UPDATE**
After researching more on this topic and also on undefined behavior, I came across this in a book on C, source is given at the end.
Calling Convention
Calling convention indicates the order in which arguments arepassed to a function when a function call is encountered. There are two possibilities here:
Arguments might be passed from left to right.
Arguments might be passed from right to left.
C language follows the second order.
Consider the following function call:
fun (a, b, c, d ) ;
In this call it doesn’t matter whether the arguments are passed from left to right or from right to left. However, in some function call the order of passing arguments becomes an important consideration. For example:
int a = 1 ;
printf ( "%d %d %d", a, ++a, a++ ) ;
It appears that this printf( ) would output 1 2 3. This however is not the case. Surprisingly, it outputs 3 3 1.
This is because C’s calling convention is from right to left. That is, firstly 1 is passed through the expression a++ and then a is incremented to 2. Then result of ++a is passed. That is, a is incremented to 3 and then passed. Finally, latest value of a, i.e. 3, is passed. Thus in right to left order 1, 3, 3 get passed. Once printf( ) collects them it prints them in the order in which we have asked it to get them printed (and not the order in which they were passed). Thus 3 3 1 gets printed.
**Source: "Let Us C" 5th edition, Author: Yashwant Kanetkar, Chapter 5: Functions and Pointers**
Regardless of whether this question is a duplicate or not, I found this new information to be helpful to me, so decided to share. Note: This also supports the claim presented by Mr.Zurg in the comments below.
Unfortunately for all of those who read that book it is totally wrong. The draft C99 standard clearly make this code undefined behavior. A quick check with the Wikipedia entry on undefined behavior contain a similar example and identifies it as undefined. I won't leave it at that but there are other easily accessible sources that get this right without having to resort to the standard.
So what does the standard say? In section 6.5 Expressions paragraph 3 says:
The grouping of operators and operands is indicated by the syntax.74)
Except as specified later (for the function-call (), &&, ||, ?:, and
comma operators), the order of evaluation of subexpressions and the
order in which side effects take place are both unspecified.
So unless specified the order of evaluation of sub-expressions is unspecified, and further section 6.5.2.2 Function calls paragraph 10 says:
The order of evaluation of the function designator, the actual
arguments, and subexpressions within the actual arguments is
unspecified, but there is a sequence point before the actual call.
So in your example:
printf ( "\n%d %d %d", k == 35, k = 50, k > 40 ) ;
^ ^ ^ ^
1 2 3 4
sub-expression 1 to 4 could be evaluated in any order and we have no way of knowing when the side effects from each sub-expression will take place although we know they all have to take effect before the function is actually called.
So k = 50 could be evaluated first or last or anywhere in between and regardless of when it is evaluated the side effect of changing the value of k could take place immediately after or not until the actual function is executed. Which means the results is unpredictable could conceivably change change during different executions.
So next we have to tackle how this becomes undefined behavior. This is covered in section 6.5 paragraph 2 which says:
Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an
expression.72) Furthermore, the prior value shall be read only to
determine the value to be stored.73)
So in your example we are not modifying k more than once but we are using the prior value to do other things besides determine the value to be stored. So what are the implications of undefined behavior? In the definition of undefined behavior the standard says:
Possible undefined behavior ranges from ignoring the situation
completely with unpredictable results, to behaving during translation
or program execution in a documented manner characteristic of the
environment (with or without the issuance of a diagnostic message), to
terminating a translation or execution (with the issuance of a
diagnostic message).
So the compiler could ignore it or could also produce unpredictable results, which covers a pretty wide range of undesirable behaviors. It has infamously been said that:
When the compiler encounters [a given undefined construct] it is legal
for it to make demons fly out of your nose
which sounds pretty undesirable to me.

undefined behaviour in C [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Parameter evaluation order before a function calling in C
order of evaluation of function parameters
What will be the output of the following code:
n=5;
printf("%d %d\n", ++n, power(2, n));
output=32
shoulld not be the output be 2^6 =64?
will different compilers give different result?
Order of evaluation of function arguments is unspecified. The compiler can compute the arguments in any order it pleases, but it must do it in some particular order (so there's no undefined behaviour here). The output can be either 32 or 64.
UPD: this is wrong, there's UB here, see here.
Contrary to what other answers say, the code may indeed exhibit undefined behavior.
As has been stated, the order of evaluation of function arguments is unspecified in C. In your program, you have an expression composed of several subexpressions:
ex0(ex1, ex2, ex3(ex4, ex5));
There is only a partial ordering between these subexpressions: ex4 and ex5 must obviously be evaluated before ex3 can be evaluated, and ex1, ex2, and ex3 must be evaluated before ex0 can be evaluated. Other than that, the order of evaluation of the subexpressions is unspecified, and it is up to your compiler to decide the order in which to evaluate the subexpressions.
There are certain, valid orders of evaluations that yield undefined behavior. For example, if ++n is evaluated before power(2, n), the results are undefined: there is a sequence point after the evaluation of all of the arguments to a function but not before or between, and the C Language Standard very clearly states (C99 §6.5/2; emphasis mine):
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
If ++n is evaluated first, this rule is violated because n is modified by ++n and n is read for the call to power(2, n) without a sequence point between those two steps.
A program that exhibits undefined behavior may produce any result: it may crash, it may print an unexpected answer, or it may appear to work as you expect it to work. Since your program potentially exhibits undefined behavior, it's difficult to discuss with certainty the actual behavior that you see. It is best to avoid writing programs that potentially (or worse, actually) exhibit undefined behavior.
And what does your power function contain? I just checked C math libraries pow function. I had to cast it to <int> like this;
#include <cstdio>
#include <cmath>
using namespace std;
int main () {
int n=5;
printf("%d %d\n", ++n, (int)pow(2.0, n));
return 0;
}
Output: 6 64
I used Microsoft Compiler(used by Visual Studio). Hope it helps.

Resources