So, I'm following "Let Us C" book, and they have an example for pointers, can you explain why the value of i and j change values in this scenario?:
main( )
{
int i = 3, *j, **k ;
j = &i ;
k = &j ;
printf ( "\nAddress of i = %u", *k ) ;
printf ( "\nAddress of j = %u", &j ) ;
}
Output
Address of i = 65524 Address of j = 65522
I understand in C that new variable declarations for example int i =3; int k=5 are assigned different memory locations by C, just cant seem to wrap my head around why this is outputting different values?
You are expecting *k (Same as address of i) and &j (address of j) to be same. They are different type int * v/s int ** and different values.
Never use %u to print addresses rather use:
printf ( "\nAddress of i = %p", (void *)*k ) ;
On the other hand, if you compare &j and k, those should be same.
For example:
printf ( "%p v/s %p\n", (void *)&j, (void *)k);
Because you are printing the pointer to k in the first printf statement, not the actual value of k. k holds the value of j's reference, so if you wanted the two statements to be equal, just print k.
Point 1: use %p to print the address. Also, cast the corresponding argument to (void *)
Point 2: *k (type int *) and &j (type int **) are two different things. Maybe you wanted to print either of
k and &j (both int **)
*k and j (both int *)
printf ( "\nAddress of i = %u", *k );
Here *k prints the value stored at j not the address of j.
To get the address of j, you need to print k without de-referencing it.
Assume that your variables are stored in following location.
Note: Addresses are just an assumption.
Now *k means de-reference the value stored at k (ie) value stored at memory location 200.
Value stored at 200 is 100 which is the address of i,not the address of j.
When your program start, the OS kernel decides, based on many criteria, where to put your program and how to map it into memory.
So, when you start it several time in a row, the memory location may or may not change.
This is why you can't hard-code absolute memory location in your program, you always pick a start point how know (for instance, the first element of an array) and navigate in your memory from here.
when your program starts, each variable gets a place in memory:
int i = 3, *j, **k ;
in your case, we know these adresses got decided:
address of (int i) = 65524
address of (int* j) = 65522
address of (int** k) = unknown
the operator & gets the adress of the variable, so you get the output you observe.
Given the code
int i = 3, *j, **k ;
j = &i ;
k = &j ;
then the following are true:
**k == *j == i == 3
*k == j == &i
k == &j
That is, the expressions **k, *j, and i all have type int and evaluate to 3, the expressions *k, j, and &i all have type int * and evaluate to the address of i, and the expressions k and &j have type int ** and evaluate to the address of j.
So,
printf( "value of i = %d\n", i );
printf( "value of i (through j) = %d\n", *j );
printf( "value of i (through k) = %d\n", **k );
printf( "address of i = %p\n", (void *) &i );
printf( "address of i (through j) = %p\n", (void *) j );
printf( "address of i (through k) = %p\n", (void *) *k );
printf( "address of j = %p\n", (void *) &j );
printf( "address of j (through k) = %p\n", k );
printf( "address of k = %p\n", (void *) &k );
Use the %p conversion specifier to print pointer values. It expects a void * as its corresponding argument, and this is one of the few places (probably the only place) in C where you need to explicitly cast a pointer value to void *.
Related
#include<stdio.h>
void f(int *p, int *q)
{
p = q;
*p = 2;
}
int i = 0, j = 1;
int main()
{
f(&i, &j);
printf("%d %d \n", i, j);
getchar();
return 0;
}
This code prints 0,2,why it does'nt print 0,1 because after *p=2 the value of j is assigned 1 right?can anyone help me
Inside f you are assigning the pointer p the pointer value of q.
Means - after p = q;, both p and q point to the same int which is j.
That's why you get 0,2.
"after *p=2 the value of j is assigned 1 right?"
No, function f() ends at the closing } brace, and
j was assigned the value of 1 before main() begins.
The line
int i = 0, j = 1;
could equally well be further up, before function f().
"because after *p = 2; the value of j is assigned by 1 right?"
No. You seem to confuse here something very hard in terms of control flow and scope. The definition of f is placed before the definitions of the global variables i and j.
That doesn't mean that the global variables get assigned after the function.
int i = 0, j = 1;
are definitions of i and j (declaration with immediate initializations) at global scope, not assignments.
The value of j 2 after the call to f is correct because:
j is passed by reference to f and its address is assigned to the pointer parameter q.
The value of the pointer q is assigned to the pointer p.
p is dereferenced then which points to j in the caller and assigns 2 to j.
Here is what happens:
statement i j p q
-----------------------------------------
int i = 0, j = 1; 0 1 - -
f(&i, &j); 0 1 &i &j
p = q; 0 1 &j &j
*p = 2; 0 2 &j &j
printf("%d %d \n", i, j); 0 2 - -
In the following code why doesn't the address of j gets overwritten in p when we call the foo function?
#include <stdio.h>
int main()
{
int i = 97, *p = &i;
foo(&i);
printf("%d ", *p);
}
void foo(int *p)
{
int j = 2;
p = &j;
printf("%d ", *p);
}
You are printing with foo - which sets p to 2, then you call a print to p, which is still set to 97 in that scope. foo does not set p globally.
Because p in main is another variable than p in the function. Consequently, even if p is changed inside the function, the value of p in main is still the same and still points to 97.
In more details:
int main()
{
int i = 97, *p = &i; // i is 97 and p points to i
foo(&i);
printf("%d ", *p); // This prints what p points to, i.e. 97
}
void foo(int *p)
{
int j = 2; // Here p still points to i in main
p = &j; // Now p points to j, i.e. the value 2
printf("%d ", *p); // So this prints 2
}
Just to repeat: The important thing is that p in main and p in foo are two different variables.
If you want the program to print 2 2 you can change the function to:
void foo(int *p)
{
int j = 2;
*p = j; // Change this line. This will change i in main
// and thereby also the value that p in main points to
printf("%d ", *p);
}
Below are the steps:
int main()
{
int i = 97;
int* p = &i; // 1. p points to i, i is 97.
foo(&i); // 2. Pass the address of i by value.
printf("%d ", *p); // 6. Print the value of i as neither p nor i have not changed inside foo().
}
// I've renamed the parameter name from p to q for clarity. q is local to
// foo() only; changes made to q are only visible within foo().
void foo(int* q)
{ // 3. q contains a copy of i's address.
int j = 2;
q = &j; // 4. q is set to the address of j.
printf("%d ", *q); // 5. Print the value of j.
}
If you would have done *q = 2 inside foo() you would have changed i's value to 2. That's because q contains the address of i.
The p in main is a different object in memory than the p in foo. Writing to one has no effect on the other. If you want foo to update the value of p in main, then you must pass a pointer to p:
#include <stdio.h>
int main()
{
int i = 97, *p = &i;
foo(&p);
printf("%d ", *p);
}
void foo(int **p)
{
int j = 2;
*p = &j;
printf("%d ", **p);
}
WARNING - doing this will invoke undefined behavior, since p will point to an object that no longer exists - once foo exits, j no longer exists, and p will be an invalid pointer. You may get the output you expect, or you may not.
In order for a function to write to a parameter, you must pass a pointer to that parameter:
void foo( T *ptr )
{
*ptr = new_value(); // updates the thing ptr points to
}
void bar( void )
{
T var; // var is an instance of T
foo( &var ); // have foo update the value of var
}
This is true for any non-array type T, including pointer types. If we replace T with the pointer type P *, we get
void foo( P * *ptr )
{
*ptr = new_value(); // updates the thing ptr points to
}
void bar( void )
{
P * var; // var is an instance of P *
foo( &var ); // have foo update the value of var
}
The semantics are exactly the same - the only thing that's changed is that var starts out as a pointer type.
Things get weird with array types, which we're not going to go into quite yet.
I am trying to wrap my head around "pointer to a pointer". And I tried some experiments and I got stuck here for a while:
int array[5] = {4 , 5 ,6 ,7 ,8};
int *p = array;
int **pp = &p;
for ( int i = 0; i < 4; i ++)
{
printf("\nprinting\n");
printf("Source: %d\n", array[i]);
printf("Output by pointer: %d, %d\n", p[i], *(p + i));
printf("Output by pointer to a pointer: %d, %d\n", *pp[i], **(pp + i) );
}
And I got this as output:
printing
Source: 4
Output by pointer: 4, 4
Output by pointer to a pointer: 4, 4
printing
Source: 5
Output by pointer: 5, 5
I don't understand why after 1 loop, the program stop at the 2nd loop- line 9. Did I misunderstand anything basic knowledge or something else.
Thank you for reading.
Change the last printf to:
printf("Output by pointer to a pointer: %d, %d\n", (*pp)[i], *(*pp + i) );
You're basically using *pp in place of p, but the * operator doesn't group as tightly as [] so you need to use parentheses in the first form. In the second form, you need to dereference pp before adding i, after which the result is dereferenced.
For starters it is unclear why there is used the magic number 4 in the loop instead of the number 5 that is the number of elements in the array
for ( int i = 0; i < 4; i ++)
^^^^^
The pointer pp does not point to first element of an array. It points to a single object
int **pp = &p;
So these expressions
*pp[i] (that is equivalent to *(pp[i] )
and
**(pp + i)
does not make sense.
An expression using the pointer p can be written using the pointer pp like *pp.
So these correct expressions
p[i]
and
*(p + i)
can be written using the pointer pp the following way (just substitute p for *pp taking into account operation precedences)
( *pp )[i]
and
*( *pp + i )
You acesses to pointer thru pointer-to-pointers are wrong:
you must access the pointee as the array:
int array[5] = {4 , 5 ,6 ,7 ,8};
int *p = array;
int **pp = &p;
for ( int i = 0; i < 4; i ++)
{
printf("\nprinting\n");
printf("Source: %d\n", array[i]);
printf("Output by pointer: %d, %d\n", p[i], *(p + i));
printf("Output by pointer to a pointer: %d, %d\n", (*pp)[i], *(*pp + i) );
}
This line is wrong
printf("Output by pointer to a pointer: %d, %d\n", *pp[i], **(pp + i) );
You need to change it to
printf("Output by pointer to a pointer: %d, %d\n", (*pp)[i], *(*pp + i) );
so that you dereference the double pointer before using it as a normal pointer.
You can think of it like this:
p is the same as (*pp)
In other words - in a valid expression that uses p you are allowed to substitute p with (*pp). That is
p[i] --> (*p)[i]
*(p + i) --> *((*pp) + i) --> *(*pp + i)
Notice that the parenthesis is important. The parenthesis can be removed in the second example but not in the first as [] has higher precedence than *.
Doing pp + i generates a pointer that doesn't point to any valid object. So when you dereference it using **(pp + i) you do an illegal access an your program crashes.
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 4 years ago.
#include<stdio.h>
void foo(int*);
int main()
{
int i = 97, *p = &i;
foo(p);
printf("%d ", *p);
getch();
}
void foo(int *p)
{
int j = 2;
p = &j;
printf("%d ", *p);
}
Output is 2 97
Why not 2 2 ?
pointer p holds the address of j now so why 97 is printed ?
You can imagine the function call and its definition the following way. For clarity I'll rename the function parameter as q.
foo(p);
void foo( /*int *q*/ )
{
int *q = p;
int j = 2;
q = &j;
printf("%d ", *q);
}
As it is seen the function parameter (in this case q) is a local variable of the function that is initialized by the value of an argument (in this case by the value of the argument p)
So any changes of the local variable (q) do not influence on the original argument (p).
After exiting the function the local variable will not be alive.
If you want to change the argument itself you should pass it by reference. For example
void foo( int **p )
{
int j = 2;
*p = &j;
printf("%d ", **p);
}
However after exiting the function the original argument/variable p will be invalid because it stores the address of a non-alive local variable of the function j.
So an attempt to access the memory that was occupied by the function's local variable j results in undefined behavior of the program.
You could make the program correct by declaring the local variable j as having static storage duration. For example
void foo( int **p )
{
static int j = 2;
*p = &j;
printf("%d ", **p);
}
and call the function like
foo(&p);
In foo, you assign a new value to p. However this is a copy of the value of p in main, so the change is not visible in main.
If you dereferenced p, then it would change the value if i in main:
void foo(int *p)
{
*p = 2;
printf("%d ", *p);
}
p = &j;
just changes the value of the local variable p. This has no effect on the caller's p variable (because p was passed by value) or the variable that p previously pointed to (because you didn't indirect through it). If you want to change the caller's data, write:
*p = j;
Go through the above code line by line. Here I have written comments as control passes through each of the lines...
#include<stdio.h>
void foo(int*);
int main()
{
int i = 97, *p = &i; //Lets assume i has address 2000
foo(p); //p contains 2000 which is passed to foo. go to foo at 1.
printf("%d ", *p); // when control comes back no change to p it
//still points to 2000 which stores 97
getch();
}
void foo(int *p) 1: // in foo another local variable p is created.
//Let's call this lp. lp has now address 2000. i.e lp
//and p both point to i but one locally exists in a
// function and will be destroyed when control comes out
// of the function
{
int j = 2;
p = &j; // now local p i.e lp points to another var j
// address. Suppose lp has address 3000 now.
printf("%d ", *p); //val at address in lp is 2
}
COMPOUND LITERALS:
#include<stdio.h>
struct s{
int x;
int y;
};
int main(){
int j = 5;
printf("\n &j : %p \n",&j);
struct s *p = &(struct s){j++};
printf("\n p : %p &j : %p x : %d y : %d \n",p,&j,p->x,p->y);
return 0;
}
o/p:
-----
&j : 0x7fff416b74ec
p : 0x7fff416b74d0 &j : 0x7fff416b74ec x : 5 y : 0
a] Why is p not holding the address of j ?
b] why is j not being typecast to struct s ?
a) p not holds the address of j because p point to freshly created structure.
if you want, that p point to j, you should write:
int * p = &j;
b) j is int local (stack) variable, so i see no way, how it can be cast into the structure.
#David C. Rankin, i've reformed my answer
The statement
struct s *p = &(struct s){j++}; // compiler should raise a warning
is incomplete. It should be like
struct s *p = &(struct s){.x = j++};
or
struct s *p = &(struct s){.y = j++};
The uninitialized member will be set ti 0 by default.
The reason that p doesn't hold the address of j is clear that p is holding the address of new object (compound literal), not the address of j itself.
for your first question,, p is of struct type and j is of integer type and you have to make the pointer and the variable of same datatype...
like int *p = &j; //where j is of int type.
j is of integer type(primitive data) and you are trying to convert it into complex datatype(object).. thus, you are trying to do boxing and unboxing.. which are not concepts of c or c++...