In the code below, I'm confused about the working of 3 line.If anyone explains it ,I will be very grateful.
Thank you.
#include< iostream >
using namespace std;
int main()
{
1. char s[]="abcdef";
2. char *p=s;
3. *p++=*++p;
4. cout<<s;
5. return 0;
}
Before the line *p++=*++p;, p points to the start of the array s.
The ++p in the right hand-side of the line will increment p by one and so it now points to b. Dereferencing it with * will give the value b and so the right hand side evaluates to b.
In the left hand side, since the post-increment operator is used, the value of p will not immediately change. Thus, the value b from the RHS will be set to the same memory location. Because of the post-increment operator, p will point to the character c of the array.
Thus, the char array will remain the same after this line and so abcdef will be printed. p however will point to the character c of the array.
Note that the above is valid only since c++17. From en.cppreference.com/w/cpp/language/eval_order: In every simple assignment expression E1=E2 and every compound assignment expression E1#=E2, every value computation and side-effect of E2 is sequenced before every value computation and side effect of E1
Related
int a=5; int *p=&a;
I want to increment the value of a so I tried below two methods but why they are giving different values
why a=*(p)++; is giving 5
but a=*(p)+1; is giving 6
In the line a=*(p)++; the () around p don't do anything and the line is parsed as a = (*(p++)); since postfix increment has higher precedence than indirection.
So you are incrementing the pointer, not the variable that the pointer points to. The postfix increment results in the value of the pointer before it was incremented, which you then dereference to give you the current value of a.
Then the line effectively becomes a = a;, doing nothing, except that p now points one-past a.
The line a=*(p)+1; is parsed as a = ((*p) + 1); since indirection has higher precedence than addition. This is effectively a = a + 1;, doing what you want.
There is however no point in using assignment at all. Just write (*p)++; to increment a through the pointer.
This piece of code:
int scores[] {1,2,3,4};
int *score_ptr {scores};
//let's say that initial value of score_ptr is 1000
std::cout<<*score_ptr++;
produces the output:
1
As * and ++ have same precedence and then associativity is from right to left shouldn't we apply ++ operator first that is to increase the pointer first and then *(dereference) it?
So accordingly score_ptr will be increased to 1004 and then dereferencing it will give the second element of scores which is 2.
How and why does this give me output of 1 instead of 2?
As * and ++ have same precedence
No, postfix operator++ has higher precedence than operator*; then *score_ptr++ is equivalent to *(score_ptr++). Note that the postfix operator++ would increment the operand and return the original value, then *(score_ptr++) would give the value 1.
The result is prvalue copy of the original value of the operand.
On the other hand prefix operator++ returns incremented value. If you change the code to *++score_ptr (which is equivalent to *(++score_ptr)) then the result would be 2 (which might be what you expected).
The increment will happen first, it has higher precedence, it's equivalent to *(score_ptr++), but it's a post-increment, this means it will only happen after the dereferenced pointer is used, i.e. the expression reaches ;.
If you use
std::cout << *++score_ptr;
Then you have a pre-increment, here it will happen beforehand, the pointer will be incremented before the value is used and the output will be 2. Equivalent to *(++score_ptr).
Note that it's allways a good idea to use parentheses, it will make the code clearer and will avoid missinterpretations.
I have searched all over for an explanation to the following code, and I can't find it anywhere. I know the output is 5, but can someone explain to me why it's 5? *b is equal to 2 after the 2nd to last line is evaluated, (I know why that is), but I don't know why b[3] equals 5. I just need the last line explained.
int* a = new int[10];
for(int i = 0; i < 10; i++)
a[i] = i;
int* b = &a[2];
cout << b[3];
After the assignment to b, it now points to the third element in the a array (i.e., the value "1").
The expression b[3] is equivalent to *(b+3) which means get the value which is three positions after b (this is essentially pointer arithmetic - b+3 is a pointer that is 3 positions after b. In this case 3 integers after b). So since b points to a[2], adding 3 makes it point to a[2+3] or a[5] which equals 5 (since the first loop makes a[i]==i).
cppreference: operator_member_access - Built-in_subscript_operator
The built-in subscript expression E1[E2] is exactly identical to the expression *(E1 + E2) except evaluation order (since C++17), that is, the pointer operand (which may be a result of array-to-pointer conversion, and which must point to an element of some array or one past the end) is adjusted to point to another element of the same array, following the rules of pointer arithmetics, and is then dereferenced.
I have been trying to learn the associativity of operators in C++ and I have come across a code segment :
int a = 10;
int C = a++ + ++a + ++a +a;
I have also studied that ++a is right to left associative and a++ is left to right associative. Also + is left to right associative. But I don't understand how to apply this knowledge in this problem.
I am confused that how this statement will be parsed by my compiler?
I am also puzzled that since putting spaces don't matter much why does removing spaces like :
int C = a+++++a+++a+a; //error: lvalue required as increment operand
generate an error?
Please help me understand this concept.
Thanks!
First of all space does matter- It helps compiler to resolve ambiguity.
Whenever there is an expression, compiler parse it from right to left. It looks for all the post increment operators first and then pre increment operators as later has lower precedence than the former. So any modification done by pre-increment operator will be applied to the whole expression and then changes of post-increment will be applied in the next expression.
Explanation
++a first increments the value of a and then returns lvalue referring to a, so if a is used then it will be the incremented value.
In your case there are total two ++a, thus the value of a will be incremented to 12 and thus assigned to a. so all the a in your expression will be holding the value 12 giving you the value of c=48.
a++ first returns an rvalue whose value is a, that is the old value, and then increments a at an unspecified time before the next full expression.
In your case if you use value of a after the expression it will be 13 as in the previous expression there was only one a++.
For eg.
int a = 10;
int C = a++ + ++a + ++a +a; // Here a=12 and the post increment effect will be applied in the next expression
int B = a + a; // Here a=13 the effect of previous post increment.
Regarding Error
With no space in expression, compiler will get confused when it will parse expression and thus dosent have any value to do the assignment.
PS: lvalue is a value that can be the target of an assignment.
In C/C++ the pre-increment (decrement) and the post-increment (decrement) operators require an L-value expression as operand. Providing an R-value or a const qualified variable results in compilation error.
Putting aside the fact that it would result in UB (as no sequence points between these multiple increments of the same variable)
a+++++a+++a+a
is parsed (as parser is greedy) as
((a++)++) + (a++) + a + a
and (a++)++ is illegal when a is a built-in type as int.
What is the meaning of this line:
int* p = new int[2,2];
in the following c++ code?
#include <iostream>
using namespace std;
int main()
{
int* p = new int[2,2];
}
int* p = new int[2,2];
effectively means
int* p = new int[2];
When comma operator is used, right most value is considered as final result.
That comma between the two 2 is a "comma operator". It is rarely used in C++ and its semantic is to evaluate left part, ignore the result, and then evaluate right part. It is one of the few operators in which the order of evaluation of the operands is guaranteed (if you don't overload it).
A good compiler sould have emitted a warning because in your example the first expression has no side effects and new int[2,2] is exactly the same as new int[2].
Note that other commas in C++ are NOT the comma operator... for example the commas between arguments in a function call are not commas operators and the order of evaluation of the arguments expression is not guaranteed. Worse than that may be an "order of evaluation" doesn't exist at all:
foo(f(g()), h());
in the line above the sequence in which the functions can be called could be for example g, h, f so you cannot say neither that the first argument was evaluated before the second nor that the second was evaluated before the first.
It's creating an integer pointer and setting it to a new array.