so here is the code, till the 4th print out I easily followed it, but at the 5th print out, I don't understand
why its "5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302 "?
I have commented the line in the code which I don't understand. I look forward to your response.
"#include <stdio.h>
#include <stdlib.h>
void
f(void)
{
int a[4];
int *b = malloc(16);
int *c = 0;
int i;
printf("1: a = %p, b = %p, c = %p\n", a, b, c);
c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c[1] = 300;
*(c + 2) = 301;
3[c] = 302;
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = c + 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
//I DONT UNDERSTAND WHAT THIS LINE BELOW DOES
c = (int *) ((char *) c + 1);
*c = 500;
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
b = (int *) a + 1;
c = (int *) ((char *) a + 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}
int
main(int ac, char **av)
{
f();
return 0;
}
output:
1: a = 0x7fff65fdcb90, b = 0x1065007e0, c = 0x0
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
6: a = 0x7fff65fdcb90, b = 0x7fff65fdcb94, c = 0x7fff65fdcb91
Let's start with the basics.
c is a pointer to an array of ints.
Let this be a:
[00000000][00000000][00000000][00000000]
Every two digits is a byte, and we assume that sizeof(int) is 4 in our example, so every element in a has 4 bytes, or 8 digits.
Now, c is a pointer to the first element in a.
Let's have a look at the expression in question:
c = (int *) ((char *) c + 1);
Obviously, c is changed here, but what exactly happens is:
c is cast from int* to char*
the result of the cast is incremented, resulting in sizeof(char) being added to c. Since sizeof(char) is 1, c is incremented by 1 and points to the second byte of an element in a.
the result is cast back to int*, and reassigned to c. This second cast is actually not needed.
So, ignoring all the other code, we start from this:
a : [00000000][00000000]...
^
c -|
And go to this:
a : [00000000][00000000]...
^
c ---|
As Daniel pointed out below, if c is not correctly aligned for a pointer of type int*, you get undefined behaviour, which should be avoided.
c is a pointer-to-int, so normally c+1 refers to the address which is sizeof(int) further along in memory - usually 4 bytes on a 32-bit system.
But you cast c to char* - that is, pointer-to-char. Now, char is only 1 byte long, so (char *)c + 1 refers to the memory location 1 byte further on than c; which is in the middle of the int at c.
You then cast the result back to an int* and write 500 into it. So what you're doing is (probably) writing the 4-byte representation of 500 over the last 3 bytes of a[1] and the 1st byte of a[2]. Exactly what effect that will have depends on the endianness of your system, but that's basically what's going on.
Related
You can see that in my code I just write int k and and its printing k=-4. why not -3 because k is an integer so it will store -3 from -3.53.
{
int a,b,c,k;
int *x, *y, *z;
a=10, b=15, c=-5;
x = &a;
y = &b;
z= &c;
*z= *z +1;
*x = *x + (-2);
k = ((*z)++) - ((*x) / (*y));
printf("%d %d %d %d",*x, c, *z, k);
}
Insert a print just before the interresting line - like:
printf("%d %d %d\n", *z, *x, *y);
k = ((*z)++) - ((*x) / (*y));
Output:
-4 8 15
Since *x is less than *y the integer division ((*x) / (*y)) will give zero. So the calculation is just:
k = ((*z)++)
Here the ++ is a post increment of *z. That is: the value of *z is returned and afterwards *z will be incremented. Therefore k will get the value -4 and *z will become -3
This question already has answers here:
Pointer Arithmetic In C
(2 answers)
Pointer subtraction confusion
(8 answers)
Closed 4 years ago.
int vector[] = { 28, 41, 7 };
int *p0 = vector;
int *p1 = vector + 1;
int *p2 = vector + 2;
I know result of
printf("%p, %p, %p\n", p0, p1, p2);
is ex) 100, 104, 108
but why is the result of
printf("p2-p0: %d\n", p2 - p0);
printf("p2-p1: %d\n", p2 - p1);
printf("p0-p1: %d\n", p0 - p1);
is 2, 1, -1
not 8, 4, -4????????
when you subtract to pointers (of the same type else no sense) that computes the difference as indexes, not the difference of the addresses :
type * p1 = ...;
type * p2 = ...;
(p1 - p2) == (((char *) p1) - ((char *) p2)) / sizeof(type)
It is the same when you do vector + n, that gives the address of the element rank n, not ((char *) vector) + n. So
type * p = ...;
int n = ...;
((char *) (p + n)) == (((char *) p) + n * sizeof(type))
Given:
int x[10] = {1,2,3,4,5,6,7};
What's the difference between:
*(x+4) and (x+4) ??
*(x + 4) dereferences the fifth element of the array, which has value 4.
(x + 4) is the address of the fifth element of the array (which is the corresponding address of the value 4).
You can check what (x + 4) is, and why:
printf( "sizeof( int ) = %ld \n", sizeof( int ) );
printf( "x = %p \n", x );
printf( "(x + 4) = %p \n", (x + 4));
Sample output:
sizeof( int ) = 4
x = 0x7fff3c0e5fc0 # address of the first element
(x + 4) = 0x7fff3c0e5fd0 # address of the fifth element
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.
I need help in understanding how we got the values in the table below for Loc3 and Loc4.
When I was making a table on my own I arrived to totally different entries for those columns.
Thank you!
int x = 42; /* x is at address 100 */
int y = 13; /* y is at address 104 */
int *p; /* p is at address 108 */
int **p2; /* p2 is at address 112 */
/* Location 1 */
p = &y;
p2 = &p;
/* Location 2 */
*p2 = &x;
**p2 = 11;
/* Location 3 */
*p = 12;
/* Location 4 */
For instance, x at loc3 becomes 11 because you set **p2 to 11, which modifies the value at that memory location. (double star is a pointer to a pointer). Ampersand gets the address.
To elaborate:
*p2 = &x;
**p2 = 11;
In Loc2 you set p2 = &p, which means p2 is now pointing to the address of p, which is 108.
But now in Loc3, you set what p2 is pointing to to the address of x. In other words, since p2 was pointing to the address of p, now you're saying that p should instead point to the address of x (which is also why p becomes 100).
Then **p2 modifies the value at that address of x to be 11 (through p), hence loc3's x value becomes 11.
Location 1:
int x = 42;
int y = 13;
int *p;
int **p2;
p or p2 don't point anywhere.
Location 2:
p = &y;
p points to y.
p2 = &p;
p2 points to p.
No changes to x or y.
Location 3:
*p2 = &x;
Since p2 points to p, dereferencing p2 and assigning a value to it changes p to point to x. Same as doing p = &x.
**p2 = 11;
Dereference once to get to p, dereference again to get to x, and assign 11 to it. Same as doing: x = 11 or *p == 11.
No change to y or p2.
Location 4:
*p = 12;
Dereference p to get to x and assing 12 to it. No change to y or p2 or p.
When you start out, p and p2 are uninitialized and contain indeterminate values, hence the ?? in both entries under Loc 1.
p = &y;
assigns the location of y (104) to p.
p2 = &p;
assigns the location of p (108) to p2. Note that the type of the expression &p is char **, which matches the type of the variable p2. So after these two statements, all of the following are true:
p2 == &p == 108 // all expressions have type char **
*p2 == p == &y == 104 // all expressions have type char *
**p2 == *p == y == 13 // all expressions have type char
x == 42
Next we execute
*p2 = &x;
From above we see that *p2 is equivalent to p, so this statement assigns the address of x (100) to p, so now we have
p2 == &p == 108
*p2 == p == &x == 100
**p2 == *p == x == 42
y == 13
Next we execute
**p2 = 11;
**p2 is equivalent to *p, which is equivalent to x, so we wind up assigning the value 11 to x:
p2 == &p == 108
*p2 == p == &x == 100
**p2 == *p == x == 11
y == 13
Finally we have
*p = 12;
*p is equivalent to x, so we're assigning the value 12 to x, leaving us with:
p2 == &p == 108
*p2 == p == &x == 100
**p2 == *p == x == 12
y == 13