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.
Related
The following code
int x;
cin >> x;
int b[x];
b[5] = 8;
cout << sizeof(b)/sizeof(b[0]) << endl << b[5];
with x inputted as 10 gives the ouput:
10
8
which seems very weird to me because:
According to http://www.cplusplus.com/doc/tutorial/arrays/ we shouldn't even be able to initialize an array using a value obtained from cin stream.
NOTE: The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.
But that's not the whole story! The same code with x inputted as 4 sometimes gives the output
Segmentation fault. Core dumped.
and sometimes gives the output:
4
8
What the heck is going on? Why doesn't the compiler act in a single manner? Why can I assign a value to an array index that is larger than the array? And why can we even initialize an array using variable in the first place?
I initially mentioned this as a comment, but seeing how no one has answered, I'm gonna add it here.
What you have demonstrated above is undefined behavior. It means that you can't tell what will the outcome be. As Brian adds in the comments, it will result in a diagnostic message (which could be a warning). Since the compiler would go ahead anyway, it can be called UB as it is not defined in the standard.
i have a question on pointer concept which i could not find a logical answer to
#include<conio.h>
#include<iostream.h>
void main()
{
int arr[10];
clrscr();
cout<<*arr+5 - *arr+3;
getch();
}
even if i assign arr[0]=10; (or any other value)
the compiler gives answer 8 but how . I can not see(understand) how operator precedence and associativity does solve it.
I will be grateful to you.
Because of *arr - *arr is 0 and 5 + 3 is 8.
The result you may be expecting is the result of:
cout<<(*arr+5) - (*arr+3);
The compiler gives answer 8 because that operation is simply equivalent to: (*arr - *arr) + 5 + 3 = 8. If you want to add the scalar to the pointer and then get the referenced value, you have to use parentheses *(arr+5).
If you look at the precedence table, for example here:
http://en.cppreference.com/w/cpp/language/operator_precedence
then you'll notice that the dereference operator (*) has higher priority than addition/subtraction (+/-) operators (they are in group no. 3 and 6 respectively). This is why the first operation that is performed is getting the value that the arr variable is pointing to, i.e. this part:
*arr
After this, the addition/subtraction is performed. The value that arr is pointing to doesn't matter since it gets reducted anyway.
This is how you should read this expression:
(*arr) + 5 - (*arr) + 3
and (*arr) - (*arr) is 0, no matter what value it points to.
EDIT: What I've written above is apparently true in your case and your compiler, but look at the #Konrad Rudolph comments to this answer.
And, if you are curious, how the compiler knows if, for example, the '*' should be treated as multiplication or dereference operator: it resolves this problem by looking at the number of arguments - if there's only one, than it's derefence, and if there are two, then it's multiplying.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 8 years ago.
1.macros has always been difficult.
2.Below is the code and output is 125 and 7....Please elaborate the working
#define mul(x) (x++ * ++x * x++)
#include<iostream.h>
void main()
{
int a=4,j;
j=mul(a);
cout<<j<<endl;
cout<<a<<endl;
}
Your program results in undefined behaviour. j could be anything.
Read more here: Undefined behavior and sequence points
What I believe is happening is this.
Set a to 4.
mul is called and a is passed in.
The second multiplication (++x) has the prefix incrementer, so x (a) is increased by 1. a is now 5.
The multiplication now happens. Since the first and last have the postfix incrementer, nothing happens until after the multiplication happens. So we have 5 * 5 * 5 = 125.
Since the multiplication is done now, the postfix incrementers happen which makes x (a) 6 and then 7.
j then equals 125.
???
Profit!
EDIT:
This is explaining the behavior that he is experiencing. I understand that this won't happen in every case.
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.
What is the output of the following code:
int main() {
int k = (k = 2) + (k = 3) + (k = 5);
printf("%d", k);
}
It does not give any error, why? I think it should give error because the assignment operations are on the same line as the definition of k.
What I mean is int i = i; cannot compile.
But it compiles. Why? What will be the output and why?
int i = i compiles because 3.3.1/1 (C++03) says
The point of declaration for a name is immediately after its complete declarator and before its initializer
So i is initialized with its own indeterminate value.
However the code invokes Undefined Behaviour because k is being modified more than once between two sequence points. Read this FAQ on Undefined Behaviour and Sequence Points
int i = i; first defines the variable and then assigns a value to it. In C you can read from an uninitialized variable. It's never a good idea, and some compilers will issue a warning message, but it's possible.
And in C, assignments are also expressions. The output will be "10", or it would be if you had a 'k' there, instead of an 'a'.
Wow, I got 11 too. I think k is getting assigned to 3 twice and then once to 5 for the addition. Making it just int k = (k=2)+(k=3) yields 6, and int k = (k=2)+(k=4) yields 8, while int k = (k=2)+(k=4)+(k=5) gives 13. int k = (k=2)+(k=4)+(k=5)+(k=6) gives 19 (4+4+5+6).
My guess? The addition is done left to right. The first two (k=x) expressions are added, and the result is stored in a register or on the stack. However, since it is k+k for this expression, both values being added are whatever k currently is, which is the second expression because it is evaluated after the other (overriding its assignment to k). However, after this initial add, the result is stored elsewhere, so is now safe from tampering (changing k will not affect it). Moving from left to right, each successive addition reassigns k (not affected the running sum), and adds k to the running sum.