TL;DR
Your code provokes Undefined Behavior, as already mentioned in Morlacke’s Answer. Other than that, it seems that you’re having problems on understanding how pointers work. See references for tutorials.
First, From your comments
When you say that there’s memory allocated for ip in this case:
int i = 10;
int *ip;
ip = &i;
What happens is:
- You declare an
intvariable callediand assign the value10to it. Here, the computer allocates memory for this variable on the stack. Say, at address0x1000. So now, address0x1000has content10. - Then you declare a pointer called
ip, having typeint. The computer allocates memory for the pointer. (This is important, see bellow for explanation). Your pointer is at address, say,0x2000. - When you assign
ip = &i, you’re assigning the address of variableito variableip. Now the value of variableip(your pointer) is the address ofi.ipdoesn’t hold the value10–idoes. Think of this assignment asip = 0x1000(don’t actually write this code). - To get the value
10using your pointer you’d have to do*ip– this is called dereferencing the pointer. When you do that, the computer will access the contents of the address held by the pointer, in this case, the computer will access the contents on the address ofi, which is10. Think of it as:get the contents of address 0x1000.
Memory looks like this after that snippet of code:
VALUE : 10 | 0x1000 |
VARIABLE : i | ip |
ADDRESS : 0x1000 | 0x2000 |
Pointers
Pointers are a special type of variable in C. You can think of pointers as typed variables that hold addresses. The space your computer allocates on the stack for pointers depends on your architecture – on 32bit machines, pointers will take 4 bytes; on 64bit machines pointers will take 8 bytes. That’s the only memory your computer allocates for your pointers (enough room to store an address).
However, pointers hold memory addresses, so you can make it point to some block of memory… Like memory blocks returned from malloc.
So, with this in mind, lets see your code:
NODE *hi;
printf("\nbefore malloc\n");
printf("\naddress of node is: %p",hi);
printf("\naddress of next is: %p",hi->next);
- Declare a pointer to
NODEcalledhi. Lets imagine this variablehihas address0x1000, and the contents of that address are arbitrary – you didn’t initialize it, so it can be anything from zeroes to a ThunderCat. - Then, when you print
hiin yourprintfyou’re printing the contents of that address0x1000… But you don’t know what’s in there… It could be anything. - Then you dereference the
hivariable. You tell the computer: access the contents of the ThunderCat and print the value of variablenext. Now, I don’t know if ThunderCats have variables inside of them, nor if they like to be accessed… so this is Undefined Behavior. And it’s bad!
To fix that:
NODE *hi = malloc(sizeof NODE);
printf("&hi: %p\n", &hi);
printf(" hi: %p\n", hi);
Now you have a memory block of the size of your structure to hold some data. However, you still didn’t initialize it, so accessing the contents of it is still undefined behavior.
To initialize it, you may do:
hi->id = 10;
hi->next = hi;
And now you may print anything you want. See this:
#include <stdio.h>
#include <stdlib.h>
struct node {
int id;
struct node *next;
};
typedef struct node NODE;
int main(void)
{
NODE *hi = malloc(sizeof(NODE));
if (!hi) return 0;
hi->id = 10;
hi->next = hi;
printf("Address of hi (&hi) : %p\n", &hi);
printf("Contents of hi : %p\n", hi);
printf("Address of next(&next): %p\n", &(hi->next));
printf("Contents of next : %p\n", hi->next);
printf("Address of id : %p\n", &(hi->id));
printf("Contents of id : %d\n", hi->id);
free(hi);
return 0;
}
And the output:
$ ./draft
Address of hi (&hi) : 0x7fffc463cb78
Contents of hi : 0x125b010
Address of next(&next): 0x125b018
Contents of next : 0x125b010
Address of id : 0x125b010
Contents of id : 10
The address of variable hi is one, and the address to which it points to is another. There are several things to notice on this output:
hiis on the stack. The block to which it points is on the heap.- The address of
idis the same as the memory block (that’s because it’s the first element of the structure). - The address of
nextis 8 bytes fromid, when it should be only 4(after allints are only 4 bytes long) – this is due to memory alignment. - The contents of
nextis the same block pointed byhi. - The amount of memory “alloced” for the
hipointer itself is 8 bytes, as I’m working on a64bit. That’s all the room it has and needs. - Always
freeafter amalloc. Avoid memory leaks - Never write code like this for other purposes than learning.
Note: When I say “memory alloced for the pointer” I mean the space the computer separates for it on the stack when the declaration happens after the Stack Frame setup.
References
- SO: How Undefined is Undefined Behavior
- SO: Do I cast the result of malloc
- SO: What and where are the stack and heap?
- Pointer Basics
- Pointer Arithmetic
- C – Memory Management
- Memory: Stack vs Heap
- Memory Management
- The Lost Art of C Strucutre Packing will tell you about structures, alignment, packing, etc…
3
solved Why the address of structure and next is not same?