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

struct node
{
    int id;
    struct node *next;
};
typedef struct node NODE;
int main()
{
    NODE *hi;   
    printf("\nbefore malloc\n");
    printf("\naddress of node is: %p",hi);
    printf("\naddress of next is: %p",hi->next);
return 0;
}

The output is:

before malloc

address of node is: 0x7ffd37e99e90 address of next is: 0x7ffd37e9a470

Why both are not same?

Lokesh Sanapalli
  • 1,012
  • 3
  • 18
  • 39
  • 3
    You don't (m)allocate anything, `hi` points anywhere. Your code exhibits undefined behaviour by dereferencing `hi` (in `hi->next`). – Kninnug Sep 25 '15 at 10:47
  • Let's say int *a , where a points to a integer type, so, just like that, in the above code I defined NODE *hi, it should points struct node. Memory is already created for it, why mallocate again? – Lokesh Sanapalli Sep 25 '15 at 11:05
  • When you declare `int * a` you reserve memory for the pointer, but not what it points to. So, just like your `NODE * hi;`, you get memory for the pointer, but not the target so dereferencing it before you assign it is undefined behaviour. Declaring a pointer does not allocate memory for what it points to. – Kninnug Sep 25 '15 at 11:17
  • Understood... Thank you, – Lokesh Sanapalli Sep 25 '15 at 11:39
  • Mode struct node *next so it's the first member of the structure. The address of a structure and the first member of a structure is the same (probably even if the address is uninitialized). There may be an exception to this in C++ with virtual functions, (I've read that some internal data may precede the first declared member of a structure or class). – rcgldr Sep 25 '15 at 17:44

3 Answers3

3

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:

  1. You declare an int variable called i and assign the value 10 to it. Here, the computer allocates memory for this variable on the stack. Say, at address 0x1000. So now, address 0x1000 has content 10.
  2. Then you declare a pointer called ip, having type int. The computer allocates memory for the pointer. (This is important, see bellow for explanation). Your pointer is at address, say, 0x2000.
  3. When you assign ip = &i, you're assigning the address of variable i to variable ip. Now the value of variable ip (your pointer) is the address of i. ip doesn't hold the value 10 - i does. Think of this assignment as ip = 0x1000 (don't actually write this code).
  4. To get the value 10 using 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 of i, which is 10. 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);
  1. Declare a pointer to NODE called hi. Lets imagine this variable hi has address 0x1000, and the contents of that address are arbitrary - you didn't initialize it, so it can be anything from zeroes to a ThunderCat.
  2. Then, when you print hi in your printf you're printing the contents of that address 0x1000... But you don't know what's in there... It could be anything.
  3. Then you dereference the hi variable. You tell the computer: access the contents of the ThunderCat and print the value of variable next. 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:

  1. hi is on the stack. The block to which it points is on the heap.
  2. The address of id is the same as the memory block (that's because it's the first element of the structure).
  3. The address of next is 8 bytes from id, when it should be only 4(after all ints are only 4 bytes long) - this is due to memory alignment.
  4. The contents of next is the same block pointed by hi.
  5. The amount of memory "alloced" for the hi pointer itself is 8 bytes, as I'm working on a 64bit. That's all the room it has and needs.
  6. Always free after a malloc. Avoid memory leaks
  7. 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

Community
  • 1
  • 1
Enzo Ferber
  • 3,029
  • 1
  • 14
  • 24
  • @Enzo Ferber Thank you for your explanation, I have a doubt, if we declare , 'int a;' then a is the variable of data type integer, 'int *p; p = &a;' means, p is pointing to a i.e. it stores the address of a. But, in case of structures, what it lead to confusion is, if we declare 'struct node', then what is node there? I thought that it is variable, so if i declare a pointer to it, then it directly points to it. But in general, if we declare 'struct node var1;' , then var1 is a variable, can you point out the difference between var1 and node in this case? – Lokesh Sanapalli Sep 25 '15 at 16:13
  • @lokesh1729 When you declare `struct node *np;` you have a pointer to a variable of **type** `struct node`. This only allocates space for an address. When you do `struct node myNode;` you declare a variable of type `struct node` - this second method makes the computer reserve some space for the variable on the stack. If you do `struct node myNode; struct node *np; np = &myNode;` it is correct. However, you still need to initialize the variables on `myNode` in order to use it. – Enzo Ferber Sep 25 '15 at 16:21
  • @lokesh1729 What might be confusing you is the type. `struct node` alone is a type, not a variable. In `struct node myNode`, `myNode` is a variable of **`type struct node`**, and in `struct node *np`, `np` is a variable of **`type pointer to struct node`**. – Enzo Ferber Sep 25 '15 at 16:24
1

You have no malloc here. hi pointer points to something undefined. hi->next the same.

About the question. Why they should be?

I think you do not understand pointers.

Morlacke
  • 61
  • 6
-1

because next is a pointer type and it is pointing to 0x7ffd37e9a470. if you print the address if next &(hi->next), you can see both hi and hi->next has a difference of 2 (because of int id is the first element).