Favolas
Favolas

Reputation: 7243

C pointers and memory

I'm learning C and now I hit a wall. Its difficult for me to understand pointers.

Imagine I have this code:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define DELTA 33

int calls, seed=356;

int sum_ds(int a){    
 int d=DELTA;          
 calls++;               
 return a+d+seed; 
}                       

int main() {
    int num;                                
    int *ptr;
    int **handle;

     num = 14;                              
     ptr = (int *)malloc(2 * sizeof(int));  
     handle = &ptr;
     *(*handle+0) = num;                    
     *(*handle+1) = num+1;  
     *ptr = num-2;      
     ptr = &num;        
     *ptr = sum_ds(num-2);
}

Lets go step by step trough my understanding.

1 - int calls creates a variable named calls and doesn't initializes it so it contains rubbish. It is stored on DATA and let's say with the memory address 0xFFAA.

2 - int seeds creates a variable named seeds initialized with the integer 356. It is stored on DATA and let's say with the memory address 0xFFAB.

3 - int num creates a variable named num and doesn't initializes it so it contains rubbish. It is stored on the STACK and let's say with the memory address 0xFFAC.

4 - int *ptr creates a pointer to int and does not assign any address to it. It is stored on the STACK and let's say with the memory address 0xFFAD.

5 - int **handle creates a pointer to a pointer of int and does not assign any address to it. It is stored on the STACK and let's say with the memory address 0xFFAE. (MANY DOUBTS HERE)

6 - num = 14 goes to the address 0xFFAC and stores the number 14 on it. It's done in the STACK.

7 - ptr = (int *)malloc(2 * sizeof(int)) On the HEAP it's assigned memory size for 2 ints and the address of the first memory byte (let's say 0xFFZZ) is stored (on STACK) on ptr so now *ptr points to that memory address.

8 - handle = &ptr handle now points to ptr. I believe it now points to whatever is on 0xFFZZ (MANY DOUBTS HERE)

9 - *(*handle+0) = num the pointer to the pointer of int now its assigned with the value of num (14) (MANY MANY MANY MANY DOUBTS HERE)

10 - *(*handle+1) = num+1 the pointer of pointer plus one of int now its assigned with the value of num + 1 (15) (MANY MANY MANY MANY DOUBTS HERE)

11 - *ptr = num-2 the value point by ptr it's assigned with the value of num - 2 (12). I believe it goes to the memory address 0xFFZZ and stores there the number 12.

12 - ptr = &num ptr now points to num, i believe it now points to 0xFFAC.

13 - *ptr = sum_ds(num-2) the value pointed by ptr is the returned value of sum_ds. I belive 0xFFAC it's assigned with 401 (12+33+356)

Is this right?

Upvotes: 2

Views: 471

Answers (3)

Bruno Soares
Bruno Soares

Reputation: 796

A variable has an address and stores at that address are the value that you just put:

int a = 10;

Right?

A pointer is a kind of variable that stores the address of another variable. So...

int a = 10;
int *p = &a;

This means that "p" stores the address of "a" that has the value that you want to use.

Execute this code below and you'll understand: printf("%p %p %d %d\n", p, &a, *p, a);

Upvotes: 1

P&#233;ter T&#246;r&#246;k
P&#233;ter T&#246;r&#246;k

Reputation: 116306

1 - int calls creates a variable named calls and doesn't initializes it so it contains rubbish. It is stored on DATA and let's say with the memory address 0xFFAA.

2 - int seeds creates a variable named seeds initialized with the integer 356. It is stored on DATA and let's say with the memory address 0xFFAB.

One little detail: sizeof(int) is greater than 1 (it is 4 on most mainstream platforms, so the 2nd address could not be 1 higher than the 1st. Other than that, AFAIK you are correct so far.

3 - int num creates a variable named num and doesn't initializes it so it contains rubbish. It is stored on the STACK and let's say with the memory address 0xFFAC.

4 - int *ptr creates a pointer to int and does not assign any address to it. It is stored on the STACK and let's say with the memory address 0xFFAD.

Another little detail: on most mainstream platforms, the stack grows downward, so the 4th address would be less than the 3rd. Other than that, AFAIK you are correct so far. (Moreover, addresses on the data segment, the heap and the stack would be rather different in real life.)

7 - ptr = (int *)malloc(2 * sizeof(int)) On the HEAP it's assigned memory size for 2 ints and the address of the first memory byte (let's say 0xFFZZ) is stored (on STACK) on ptr so now *ptr points to that memory address.

To be nitpicky, 'Z' is not a hexadecimal number :-) So let's say it is 0x1000 instead.

8 - handle = &ptr handle now points to ptr. I believe it now points to whatever is on 0xFFZZ (MANY DOUBTS HERE)

No, handle now contains the address of ptr, that is 0xFFAD. Indirectly though - through ptr - it indeed points to 0x1000 (was 0xFFZZ in your example).

9 - *(*handle+0) = num the pointer to the pointer of int now its assigned with the value of num (14) (MANY MANY MANY MANY DOUBTS HERE)

Basically correct. The notation you use is not the easiest to deal with, which makes it more difficult for you to follow what's going on. After step 8, *handle is equivalent to ptr. And due to pointers and arrays being interchangeable in many common situations, *(ptr+0) is equivalent to ptr[0], and also to *ptr.

10 - *(*handle+1) = num+1 the pointer of pointer plus one of int now its assigned with the value of num + 1 (15) (MANY MANY MANY MANY DOUBTS HERE)

Similar to the previous point, you are in effect assigning ptr[1] = num+1. Keep in mind though that ptr is int*, so the address difference between ptr and ptr + 1 equals to sizeof(int), which is, as mentioned above, usually 4.

11 - *ptr = num-2 the value point by ptr it's assigned with the value of num - 2 (12). I believe it goes to the memory address 0xFFZZ and stores there the number 12.

Yes, this overwrites the value set in step 9.

12 - ptr = &num ptr now points to num, i believe it now points to 0xFFAC.

Correct.

13 - *ptr = sum_ds(num-2) the value pointed by ptr is the returned value of sum_ds. I belive 0xFFAC it's assigned with 401 (12+33+356)

Correct. Since the previous step made *ptr equivalent to num, this call is also equivalent to num = sum_ds(num-2).

Upvotes: 4

Jerry Coffin
Jerry Coffin

Reputation: 490623

Since calls is outside any function, it's a static variable. Static variables are initialized to 0.

Since num is a local variable (auto storage class) it is not initialized.

At your point 9, *(*handle+0) = num; is probably easiest to decipher by keeping in mind that handle = &ptr, therefore *handle = ptr, so this is basically equivalent to *(ptr+0) = num;, which is (in turn) equivalent to ptr[0] = num;.

For point 10, you get pretty much the same thing, except a +1 in both cases, so it's saying ptr[1] = num+1;.

For point 11, *ptr=num-2; overwrites what was written in point 9 -- i.e., *ptr is the same as *(ptr+0), so this is equivalent to ptr[0] = num-2;

You're correct in point 12 that ptr has been set to point at num. That means in point 13, the assignment is equivalent to num=sum_ds(num-2);

Upvotes: 1

Related Questions