This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
Undefined Behavior and Sequence Points
Ok we all know that i++ increments value by 1 on next line and ++i increments on same line(please correct me if i am wrong there ) so for a sample statement of c as follows:
int a=0;
printf("%d , %d",++a,a);
the expected output should be 1 , 1 but instead it gives 1 , 0
so as one might guess what i am asking here is why does the second linking of
i print 0 instead of 1 when the value is already incremented.
So if post increment didn't increment value in the same line then what is the
difference between post and pre increment? edit : changed the name of variable from i to a to avoid grammatical confusion.
You are very wrong in your understanding of the increment operators.
i++ increments i, and returns its old value; ++i increments i,
and returns the new value. When the actual incrementation takes place
is only guaranteed to be after the preceding sequence point, and before
the next; in your code, this means before the call to printf.
Beyond that (and largely because of that), if you modify the value of an
object, you're not allowed to access it anywhere else without an
intervening sequence point, except as needed to determine the new value.
You violate this rule, so your code has undefined behavior.
It's undefined behavior. the compiler is allowed to calculate the parameters in any order. your compiler just calculate it from right to left, so the rightest parameter is 0, and the 2nd is 1.
edit: as Seth said, the compiler is only free to change the order of calculating, not to do whatever it wants, so when you don't care about the order you can freely call functions, but you should never assume that one parameter is been calculated before another.
I think your question is not about how increment work. The phenomenon you have observed is about the order of passing parameter to a function. As far as I can remember, this is not defined by c++ standard, so it's a UNDEFINED BEHAVIOR. Meaning different compiler could have different implementation.
E.g.
One compiler could pass parameter from left to right, then a different could pass parameters from right to left.
You can have a better read of Sequence point here:
http://en.wikipedia.org/wiki/Sequence_point
printf("%d , %d",++i,i);
is undefined behavior.
Your are violating C sequence points rule:
(C99, 6.5p2) "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."
Once I read in some book that when a statement is like this:
printf("%d , %d",++a,a);
The execution starts from right to left but outputted as left to right. Therefore you see the out as 1 0 - 'a' is calculated first = 0 then '++a' = 1, but displayed as 1 0
This is strange but yeah that's how it works.
Hope this helps.
Related
In the following code:
#include<iostream>
using namespace std;
int main()
{
int A[5] = {10,20,30,40,50};
// Let us try to print A[5] which does NOT exist but still
cout <<"First A[5] = "<< A[5] << endl<<endl;
//Now let us print A[5] inside the for loop
for(int i=0; i<=5; i++)
{
cout<<"Second A["<<i<<"]"<<" = "<<A[i]<<endl;
}
}
Output:
The first A[5] is giving different output (is it called garbage value?) and the second A[5] which is inside the for loop is giving different output (in this case, A[i] is giving the output as i). Can anyone explain me why?
Also inside the for loop, if I declare a random variable like int sax = 100; then A[5] will take the value 100 and I don't have the slightest of clue why is this happening.
I am on Windows, CodeBlocks, GNUGCC Compiler
Well you invoke Undefined Behaviour, so behaviour is err... undefined and anything can happen including what your show here.
In common implementations, data past the end of array could be used by a different element, and only implementation details in the compiler could tell which one.
Here your implementation has placed the next variable (i) just after the array, so A[5] is an (invalid) accessor for i.
But please do not rely on that. Different compilers or different compilation options could give a different result. And as a compiler is free to assume that you code shall not invoke UB an optimizing compiler could just optimize out all of your code and only you would be to blame.
TL/DR: Never, ever try to experiment UB: anything can happen from a consistent behaviour to an immediate crash passing by various inconsistent outputs. And what you see will not be reproduced in a different context (context here can even be just a different run of same code)
In your Program, I think "there is no any syntax issue" because when I execute this same code in my compiler. Then there is no any issue likes you.
It gives same garbage value at direct as well as in loop.
enter image description here
The problem is that when you wrote:
cout <<"First A[5] = "<< A[5] << endl<<endl;//this is Undefined behavior
In the above statement you're going out of bounds. This is because array index starts from 0 and not 1.
Since your array size is 5. This means you can safely access A[0],A[1],A[2],A[3] and A[4].
On the other hand you cannot access A[5]. If you try to do so, you will get undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.
So the output that you're seeing is a result of undefined behavior. And as i said don't rely on the output of a program that has UB.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
For the same reason, in your for loop you should replace i<=5 with i<5.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.
I tried these lines of code and found out shocking output. I am expecting some reason related to initialisation either in general or in for loop.
1.)
int i = 0;
for(i++; i++; i++){
if(i>10) break;
}
printf("%d",i);
Output - 12
2.)
int i;
for(i++; i++; i++){
if(i>10) break;
}
printf("%d",i);
Output - 1
I expected the statements "int i = 0" and "int i" to be the same.What is the difference between them?
I expected the statements "int i = 0" and "int i" to be the same.
No, that was a wrong expectation on your part. If a variable is declared outside of a function (as a "global" variable), or if it is declared with the static keyword, it's guaranteed to be initialized to 0 even if you don't write = 0. But variables defined inside functions (ordinary "local" variables without static) do not have this guaranteed initialization. If you don't explicitly initialize them, they start out containing indeterminate values.
(Note, though, that in this context "indeterminate" does not mean "random". If you write a program that uses or prints an uninitialized variable, often you'll find that it starts out containing the same value every time you run your program. By chance, it might even be 0. On most machines, what happens is that the variable takes on whatever value was left "on the stack" by the previous function that was called.)
See also these related questions:
Non-static variable initialization
Static variable initialization?
See also section 4.2 and section 4.3 in these class notes.
See also question 1.30 in the C FAQ list.
Addendum: Based on your comments, it sounds like when you fail to initialize i, the indeterminate value it happens to start out with is 0, so your question is now:
"Given the program
#include <stdio.h>
int main()
{
int i; // note uninitialized
printf("%d\n", i); // prints 0
for(i++; i++; i++){
if(i>10) break;
}
printf("%d\n", i); // prints 1
}
what possible sequence of operations could the compiler be emitting that would cause it to compute a final value of 1?"
This can be a difficult question to answer. Several people have tried to answer it, in this question's other answer and in the comments, but for some reason you haven't accepted that answer.
That answer again is, "An uninitialized local variable leads to undefined behavior. Undefined behavior means anything can happen."
The important thing about this answer is that it says that "anything can happen", and "anything" means absolutely anything. It absolutely does not have to make sense.
The second question, as I have phrased it, does not really even make sense, because it contains an inherent contradiction, because it asks, "what possible sequence of operations could the compiler be emitting", but since the program contains Undefined behavior, the compiler isn't even obliged to emit a sensible sequence of operations at all.
If you really want to know what sequence of operations your compiler is emitting, you'll have to ask it. Under Unix/Linux, compile with the -S flag. Under other compilers, I don't know how to view the assembly-language output. But please don't expect the output to make any sense, and please don't ask me to explain it to you (because I already know it won't make any sense).
Because the compiler is allowed to do anything, it might be emitting code as if your program had been written, for example, as
#include <stdio.h>
int main()
{
int i; // note uninitialized
printf("%d\n", i); // prints 0
i++;
printf("%d\n", i); // prints 1
}
"But that doesn't make any sense!", you say. "How could the compiler turn "for(i++; i++; i++) ..." into just "i++"? And the answer -- you've heard it, but maybe you still didn't quite believe it -- is that when a program contains undefined behavior, the compiler is allowed to do anything.
The difference is what you already observed. The first code initializes i the other does not. Using an unitialized value is undefined behaviour (UB) in c++. The compiler assumes UB does not happen in a correct program, and hence is allowed to emit code that does whatever.
Simpler example is:
int i;
i++;
Compiler knows that i++ cannot happen in a correct program, and the compiler does not bother to emit correct output for wrong input, hece when you run this code anything could happen.
For further reading see here: https://en.cppreference.com/w/cpp/language/ub
The is a rule of thumb that (among other things) helps to avoid uninitialized variables. It is called Almost-Always-Auto, and it suggests to use auto almost always. If you write
auto i = 0;
You cannot forget to initialize i, because auto requires an initialzer to be able to deduce the type.
PS: C and C++ are two different languages with different rules. Your second code is UB in C++, but I cannot answer your question for C.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 7 years ago.
in the below code i am trying to add two elements of array with the increment operator, but i am getting the output sum to be wrong. kindly help me if i made any mistake in the code
#include <stdio.h>
int main(void) {
int a[2];
int top=-1;
a[++top]=10;
a[++top]=20;
printf("a0 is %d \n",a[0]);
printf("a1 is %d \n",a[top]);
printf("value of sum is %d \n",a[top]+a[--top]);
}
the output of last line should be 30 as i and summing the two values in a array. but the out put i get is as follows
a0 is 10
a1 is 20
value of sum is 20
Your program has unspecified behavior. In the expression a[top]+a[--top], the C and C++ language standards do not specify which of a[top] and a[--top] will be evaluated first, and they don't specify when the -- operator is executed relative to other expressions. Compilers can evaluate this as they see fit. Yours is computing --top first, setting top to 0, and then is calculating a[0]+a[0], yielding 20.
Don't use a variable twice in an expression in which you pre- or post- increment or decrement it.
To understand why this is happening, change your last printf to print out top and the sum in one line, like this:
printf("top is %d and the value of the sum is %d \n",top,a[top]+a[--top]);
This should make it apparent that the pre-increment operation is not happening at the point in execution that you think it is.
Try to calculate and print
int y1 = a[top];
int y1 += a[--top];
top = 1;
int y2 = a[top] + a[--top];
this could help you.
The point is that the execution of a[--top]; in your code is done before the execution of a[top] because they are not specified.
Here, in this line:
printf("value of sum is %d \n",a[top]+a[--top]);
Due to --top, top becomes 0 again (--top is --1).
Then a[0] and a[0] are added, and it does not give expected output.
I think it's due to high precedence order of -- operator.
As has been said already, it's better to calculate separately and then print.
PS: Please tell me if anything of the above is wrong or not fully correct. I like to learn from mistakes.
after all, we typically have to state what a function returns; that is, if we return a value from a function we are always making a promise about the return value (how else would a caller what to expect).
int area(int lenght, int width)
// pre-conditions : lenght and width are positive
// post-condition : returns a positive value that is the area
{
if (lenght <= 0 || width <= 0) error("area() pre-condition");
int a = lenght * width;
if (a <= 0) error("area() post-condition");
return a;
}
This is a simple example of using pre-condition and post-condition, but what I can not understand is what the author says after showing the example:
"We couldn't check the complete post-condition, but we checked the part that said that it should be positive".
What does it mean ? Why we couldn't check the complete post-condition ? In my understanding in this case as post-condition we just need to check that the variable a is positive, am I wrong ?
Than the author ask me this question :
Find a pair of value so that the pre-condition of this version of area holds, but the post-condition doesn't.
Is it not impossible ??
In my understanding in this case as post-condition we just need to check that the variable a is positive, am I wrong ?
Yes. Note the full post-condition...
returns a positive value that is the area
It's possible to pass values of length and width such that a does not come out to the correct area due to overflow.
Why we couldn't check the complete post-condition ?
Because part of the post-condition is "that is the area". We haven't checked that; and it's not trivial to check that the result of the multiplication is equal to the mathematically expected value.
Is it not impossible ??
If the multiplication overflows, giving undefined behaviour, then you might get a negative result from two positive inputs.
Your example is most certainly about the signed arithmetic overflow in lenght * width.
In this case this is a very bad illustration of the notion of post-condition. The expectation that should be delineated to explain pre-conditions is:
If the function is called with arguments that satisfy the pre-condition, then it does not invoke undefined behavior.
If the function is called with arguments that satisfy the pre-condition, then the post-condition holds when the function terminates.
The example in your question illustrates the first point, not the second one.
The author thinks that the function returns a negative “area” for some input, but the author is wrong: the function can only return the correct result (a positive value that is the correct area) or invoke undefined behavior. That this undefined behavior can lead to a appearing negative on some compilation platforms is irrelevant. Undefined behavior is forbidden. Undefined behavior is unpredictable.
A question from a job-interview
int count = 0;
void func1()
{
for ( int i =0 ; i < 10; ++i )
count = count + 1;
}
void func2()
{
for ( int i =0 ; i < 10; ++i )
count++;
}
void func3()
{
for ( int i =0 ; i < 10; ++i )
++count;
}
int main()
{
thread(func1);
thread(func2);
thread(func3);
//joining all the threads
return 0;
}
The question is: what's the range of values count might theoreticaly take? The upper bound apparently is 30, but what's the lower one? They told me it's 10, but i'm not sure about it. Otherwise, why do we need memory barriers?
So, what's the lower bound of the range?
It's undefined behavior, so count could take on any value
imaginable. Or the program could crash.
James Kanze's answer is the right one for all practical purposes, but in this particular case, if the code is exactly as written and the thread used here is std::thread from C++11, the behavior is actually defined.
In particular, thread(func1); will start a thread running func1. Then, at the end of the expression, the temporary thread object will be destroyed, without join or detach having been called on it. So the thread is still joinable, and the standard defines that in such a case, the destructor calls std::terminate. (See [thread.thread.destr]: "If joinable() then terminate(), otherwise no effects.") So your program aborts.
Because this happens before the second thread is even started, there is no actual race condition - the first thread is the only one that ever touches count, if it even gets that far.
Starting with the easy part, the obvious upper bound is 30 since, if everything goes right, you have 3 calls to functions; each capable of incrementing count 10 times. Overall: 3*10=30.
Ad to the lower bound, they are correct and this is why - the worst-case scenario is that each time that one thread tries to increment count, the other threads will be doing so at exactly the same time. Keeping in mind that ++count actually is the following pseudo code:
count_temp = count;
count_temp = count_temp+1;
count = count_temp;
It should be obvious that if they all perform the same code at the same time, you have only 10 real increments, since they all read the same initial value of count and all write back the same added value.
First of all, I'd like to thank you guys for giving me reason me to read the standard in depth. I would not be able to continue this debate otherwise.
The standard states quite clearly in section 1.10 clause 21: The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.
However, the term undefined behavior is also defined in the standard, section 1.3.24: behavior for which this International Standard imposes no requirements... 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...
Taking Sebasian's answer regarding std::terminate into account, and working under the assumption that these threads will not throw an exception thereby causing premature termination; while the standard doesn't define the result - it is fairly evident what it may be because of the simplicity of the algorithm. In other words, while the 100% accurate answer would be that the result is undefined - I still maintain that the range of possible outcomes is well defined and is 10-30 due to the characteristic of the environment.
BTW - I really wanted to make this a comment instead of another answer, however it was too long