I'm looking at a past paper for a course I'm doing at university, and there is always a question about C pointers.
I reckon I have a reasonable grasp of how they work, however this is the question that is confusing me:
Consider running the C program fragment:
int x[4] = {0,2,4,6};
int *y;
y = &x[2];
*(x + 2) = y[1] + 1;
What is the value of the expression *y afterwards?
(a) 2
(b) 4
(c) 5
(d) 7
(e) 8
Now, in the answers to said question, it says the answer is d.
I'm super confused, seeing as:
The value of x is not declared, so I'd have thought it would be impossible to evaluate x+2
y isn't an array, so how can y[1] be evaluated?
Why is 7 the correct answer here?
x is the 4-element array. *x references the first element in that array, and *(x + 2) references the 3rd element.
*y points at index 2 (3rd element) in the x array (y = &x[2])
the final assignment sets the 3rd element of the original x array ( *(x + 2) ) to the value of y[1] + 1. since y is initialized to point at the 3rd element, y[1] will point at the final element of the original x array.
6 + 1 is assigned to the 3rd element of the x array, which *y refers to.
Things to note:
*(x + 2) is exactly the same as x[2].
&x[2] is exactly the same as &(*(x + 2)) which is the same as x + 2.
So knowing that, let's rewrite the problem:
int x[4] = {0,2,4,6};
int *y = &x[2];
*(x + 2) = y[1] + 1;
And some more rewriting:
int x[4] = {0,2,4,6};
int *y = x + 2;
x[2] = *(y + 1) + 1;
Now, let's substitute y directly into the last equation:
int x[4] = {0,2,4,6};
int *y = x + 2;
x[2] = *((x + 2) + 1) + 1;
And clean it up:
int x[4] = {0,2,4,6};
int *y = x + 2;
x[2] = x[3] + 1;
So now, let's look at the problem:
x[2] is updated with the value of x[3] + 1
So x[2] is now 7.
So x == {0, 2, 7, 6}
y still points at the value at x + 2.
So *y == 7
Lets break it down:
int x[4] = {0,2,4,6};
x [0] = 0
x [1] = 2
x [2] = 4
x [3] = 6
int *y; Pointer to an integer so y could point to any location in x
x [0] = 0 // <-- y ?
x [1] = 2 // <-- y ?
x [2] = 4 // <-- y ?
x [3] = 6 // <-- y ?
y = &x[2]; Now we have specified that y points to x[2]
x [0] = 0
x [1] = 2
x [2] = 4 // <-- y (or y[0])
x [3] = 6
*(x + 2) This is the same as x[2] so:
x[2] = y[1] + 1;
x [0] = 0
x [1] = 2
x [2] = 4 // <-- x[2]
x [3] = 6 // <-- y[1]
y[1] is 6, so y[1] + 1 = 7
Note that y[1] is the same as *(y + 1). We take the address y points too, add to it the size of one integer and obtain the contents of what it now points to.
Let consider the code step by step.
Pointer y is initialized by the address of the third element of the array (indices start from 0)
y = &x[2];
So y points to 4. So x[2] and y[0] are equivalent expressions
y[1] is the next element after y[0] that is it is 6.
y[1] + 1 will be equal to 7
*( x + 2 ) is the same as x[2] So x[2] will be set to 7. At the same time y also points to
x[2]. So *y will be equal to 7.
The key components here are that the index operator returns y1 an actual int not an address. The same for the dereference operator *(x + 2).
int a = y[1]; // a = the value of the int after y[0]
int b = *(x + 2); // b = the value of x[2] note that the index operator is just shorthand, y[1] just means *(y + 1)
// int* c = y[1]; NOT LEGAL assignment of an int to an int*
// int* d = *(x + 2); NOT LEGAL assignment of an int to an int*
I've added a table here to hopefully help clarify:
Related
Okay, I know the output for the expression (x *= y = z = 4;) is 40; but how exactly did we get 40? Can you please show me step by step.
I thought the precedence is from right to left so (2 * 4) = (z =4), I don't understand
#include <stdio.h>
#define PRINTX printf("%d\n",x)
int main (void){
int x = 2, y, z;
x *= 3 + 2;
PRINTX;
x *= y = z = 4;
PRINTX;
x = y == z;
PRINTX;
x == ( y = z );
PRINTX;
return 0;
}
No, the only way that assignment can be evaluated here is right to left.
First, note that x *= 99, for example, is shorthand for x = x * 99.
With that said,
x *= y = z = 4;
is equivalent to
z = 4;
y = z;
x *= y; // This is shorthand for x = x * 4
Consider what would happen if you tried to evaluate it the other way around:
// y is unininitialized
x *= y;
y = z;
z = 4;
It would fail.
So really,
// x = 2
int x = 2, y, z;
// x = x * (3 + 2) = x * 5 = 2 * 5 = 10
x *= 3 + 2;
// x = x * 4 = 10 * 4 = 40
x *= y = z = 4;
This can be rewritten as
int x, y, z;
x = 2; // x = 2
x = x * (3 + 2); // This is 2 * 5, so x = 10 after this
z = 4; // z = 4
y = z; // y = 4
x = x * y; // x = 10 * 4 = 40
And that's how you end up with 40.
All of the assignment operators have equal precedence, and right-to-left associativity (which affects what happens when multiple operators of equal precedence are present in an expression).
This means x *= y = z = 4 is equivalent to x *= (y = (z = 4)). z = 4 must be evaluated first (which assigns z to 4, and gives a result of 4). The assignment y = ... then gives the value y the value of 4, and also produces a result of 4. The assignment x *= ... then multiples x (which has a value 10) by 4, giving a result of 40.
(The reason x *= 3 + 2 gives x the value 10 is that addition has higher precedence than assignment, so x *= 3+2 is equivalent to x *= (3 + 2) rather than (x *= 3) + 2.)
If the assignment operators were instead left-to-right associative, x *= y = z = 4 would be equivalent to (((x *= y) = y) = z) = 4 which would not compile.
You have:
int x = 2, y, z;
x *= 3 + 2;
This is a shorthand for x = x * (3 + 2), which evaluates to 10 given that x starts at 2.
PRINTX;
x *= y = z = 4;
After this, y == z and both are set to 4; and x is 4 times its previous value of 10, hence 40.
PRINTX;
x = y == z;
This compares y and z; they're equal, so x is assigned 1 (comparisons always evaluate to 0 or 1).
PRINTX;
x == ( y = z );
This assigns z to y (leaving the value unchanged at 4); nominally, this is compared with x but the compiler can ignore the comparison. Therefore, x is unchanged and still 1.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Can anyone explain to me how this code is being calculated using operators.
#include <stdio.h>
int main(void)
{
int x = 2, y , z;
x *= 3;
printf("%d\n", x);
x = x * (3 + 2);
printf("%d\n", x);
x *= y = z = 4;
printf("%d\n", x);
x *= y += z;
printf("%d %d %d\n", x, y, z);
return 0;
}
As a result, I got the following output:
6,
30,
120,
960, 8, 4,
The operator followed by an equal sign means that the operator is applied to the variable on the left and the variable on the right, followed by an assignment to the variable on the left. You also follow the precedence operations. I have expanded the meaning below.
x *= 3;
is the same as
x = x * 3; // 6 = 2*3
The parentheses shows order of precedence
x = x * (3+2) // x was 6 from the previous line
this is
x = x * 5 // which gives 30
next
x *= y = z = 4;
means
z = 4;
y = z; //which is 4
x = x *y; // which is 120 = 30 *4
next
x *= y += z;
means
y = y + z ; // y = 4 + 4 (8)
x = x * y; // x = 120 * 8 (960)
*= multiplies left operand by right operand and assigns result to left.
x *= y = z = 4;
Works right to left, assigning 4 to z and y then multiplying x by 4.
x *= y += z;
z is added to y and result is assigned to y, then x is multiplied by y and result is assigned to x.
x*=3 means x=x*3 => x=2*3=6
x*=(3+2) means x=x*(3+2) => x=6*5=30
x*=y=z=4 means z=4, then y=4, then x=x*y => x=30*4=120
x*=y+=z means y=y+z then x=x*y => y=4+4=8 then x=120*8=960.
The first two assignments are straightforward: multiplying x by 3 gives you 6, and then by (3+2) gives you 30.
The third assignment features a chain of assignments, with 4 assigned to y and z. Since the value of an assignment is always the value of its left side after the assignment, the final multiplication x *= y multiplies x by 4, giving you 120.
The last line is the trickiest, because it features two side effects. First, y += z is evaluated, producing 8. After that x is multiplied by 8, producing its final value of 960.
Note that in the last line x is multiplied by 8, which may or may not be the value of y at the time the multiplication is performed.
int a[] = {10, 15, 20, 25};
int b[] = {50, 60, 70, 80, 90};
int *x[] = {a, b};
int *y[] = {a + 2, b + 3};
int *p;
int *q;
int **r;
p = a;
q = y[1];
r = &q;
*p = &p[3] - y[0];
r[0][1] = **r - y[0][1];
What are the contents of a and b at the end?
I figured out that *p is a[0], and &p[3] - y[0] is just 3 - 2, so a[0] = 3 - 2 = 1. Therefore, a[] = {1, 10, 15, 20} (correct me if I am wrong), but b[] is where I get lost. I have no idea how the last line of the code works. No idea on what r[0][1] refers to, so getting the contents for b[] is confusing. P.S. this is for C.
Remember that the identity *(p + k) == p[k] (or p + x == &p[k]) means that you can always rewrite dereferencing as indexing and vice-versa, so if an expression is confusing you can try a different form and see if it makes more sense.
I personally find indexing easier to reason about:
Since r = &q, both r[0] and *r are the same as q:
q[1] = *q - y[0][1];
or
q[1] = q[0] - y[0][1];
q is y[1] gives:
y[1][1] = y[1][0] - y[0][1];
y[0]is a + 2 and y[1] is b + 3:
(b + 3)[1] = (b + 3)[0] - (a + 2)[1];
which is
*(b + 3 + 1) = *(b + 3 + 0) - *(a + 2 + 1);
which is
*(b + 4) = *(b + 3) - *(a + 3);
which is
b[4] = b[3] - a[3];
that is,
b[4] = 80 - 25;
The line int **r; declares a pointer to an int *. In other words, r is a pointer to a pointer to an int. If you recall that the syntax x[y] is equivalent to *(x + y), you might get an idea for what r[0][1] does.
r[0][1] --> *((*(r + 0)) + 1)
Keeping in mind that r[0][1] is on the LHS of the assignment operator, you are storing to that memory location.
#include<stdio.h>
int main()
{
int a[5] = {5, 1, 15, 20, 25};
int x, y, z;
x = ++a[1];
y = a[1]++;
z = a[x++];
printf("%d, %d, %d", x, y, z);
return 0;
}
"x" is printed as 3, but I would have expected it to return 2? In fact if I remove the "++" and set x equal to a[1], it returns as 2. It adds 1 to any value that is actually there. Am I missing something?
"x" is printed as 3, but I would have expected it to return 2?
x = ++a[1];
Here x = 2 because of pre-increment
The you have
z = a[x++];
x ++ = x + 1 = 2+1 = 3
Hence x=3
x = ++a[1];//Increment a[1] and then assign it to x
y = a[1]++;//assign a[1] to y and then increment a[1]
z = a[x++];//assign a[2] to z and then increment x
The ++ is called an increment operator. It increases the value by 1.
In you code you have
x = ++a[1];
++ before a variable is the Pre Increment Operator. It increments the value of a[1] before assigning it to x. So the value of a[1] and x becomes 3.
The other one
y = a[1]++;
++ after the variable is the Post Increment Operator. It assigns a[1] ( which has already become 3 ) to y and then increments the value of a[1] to 4.
This link will help you
http://www.c4learn.com/c-programming/c-increment-operator/#A_Pre_Increment_Operator
x=++a[1]; // Now x got the value 2.
In this line,
z = a[x++]; // x++ will be happen after the assigning of a[2] to z. So the value of x is incremented. So the x value is became 3.
It is post increment so the z got the value as 15. Refer this link.
I have following C program, and I'm not understanding the output of the following program.
#include <stdio.h>
int main()
{
int a,b, *p1, *p2, x,y,z;
a=12;
b=4;
p1=&a;
p2=&b;
x=*p1 * *p2-6;
y=4* - *p2 / *p1+10;
printf("y=%d", y);
return 0;
}
The output of the program is 9. But what is the meaning of 4*?
What is the meaning of 4*
The * there is the multiplication operator. Only one operand, 4, is shown in that extract. The full multiplication is:
4* - *p2
which is more clearly written as
4 * -(*p2)
Write out the expression, substituting the values. We can ignore x since it is not used. Which leaves us:
y= 4* - *p2 / *p1+10;
And *p2 is b which is 4. And *p1 is a which is 12. So the expression is:
y = 4 * -4 / 12 + 10;
And this evaluates as:
y = ((4 * -4) / 12) + 10;
Which is
y = (-16 / 12) + 10;
Which is
y = -1 + 10;
The spacing in this line might be causing confusion:
y=4* - *p2 / *p1+10;
This is equivalent to:
y = 4 * (-*p2) / *p1 + 10;
but the spacing makes it look like a subtraction.
The code
4* - *p2
means
4 * (-*p2)
So * means simple multiplication here.
Get familiar with the C precedence and associativity table:
The statements will be evaluated like this (parentheses added for clarity):
x = ((*p1) * (*p2)) - 6;
x = ((12) * (4)) - 6
x = (48) - 6
x = 42
y = (4 * (-(*p2)) / (*p1)) + 10;
y = (4 * (-4) / (12)) + 10
y = (-16 / 12) + 10
y = -1 + 10
y = 9