-2

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?

Marco A.
  • 43,032
  • 26
  • 132
  • 246
Jshee
  • 2,620
  • 6
  • 44
  • 60
  • 6
    Offtopic suggestion: "Let us C" is a junk don't read it. Pick some good book on C. Also use `int main(void)` instead of `main()` and `return 0;` – Mohit Jain Jul 29 '15 at 13:06
  • Why the downvote? Im asking a question... And dont just say "use a new book" , recommend one. – Jshee Jul 29 '15 at 13:06
  • 3
    `i` and `j` are indeed different variables, so they have different addresses as you mention. What's the problem ? – Quentin Jul 29 '15 at 13:07
  • @user700070 Offtopic again(Sorry): There are some (not all) good books @ http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list – Mohit Jain Jul 29 '15 at 13:13
  • You may want to read [these](http://c-faq.com/ptrs/index.html) 17 questions and their answers. (Just click on question number to follow the answer link) – Mohit Jain Jul 30 '15 at 05:52

7 Answers7

4

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);
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
2

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.

Lawrence Aiello
  • 4,560
  • 5
  • 21
  • 35
1

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 *)
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Any recommendations on books/tutorials to better understand pointers ... super new to C – Jshee Jul 29 '15 at 13:09
1
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. enter image description here

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.

Karthick
  • 1,010
  • 1
  • 8
  • 24
0

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.

blue112
  • 52,634
  • 3
  • 45
  • 54
0

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.

Chris Maes
  • 35,025
  • 12
  • 111
  • 136
0

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

John Bode
  • 119,563
  • 19
  • 122
  • 198