简体   繁体   中英

Why does the address of a pointer var change in this scenario?

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 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 * .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM