Thread: How structure program allocate address

  1. #1
    Registered User
    Join Date
    Feb 2022
    Posts
    73

    How structure program allocate address

    I wrote structure program to know how structure store variable data and where does it store

    Code:
     #include <stdio.h>
    #include <stdlib.h>
    
    
    struct point 
    {
        int x;
        
        struct point *next; 
    };
    
    
    int main ()
    {
        struct point *new = NULL; 
        
        new = malloc (sizeof(*new));
        
        
        if ( new != NULL)
        {
            
            new -> x = 1;
     
            new -> next = NULL;
            printf("addresses of a struct variable new    : %p \n", (void*)&new);
            printf("addresses of a struct object x        : %p \n", (void*)&new -> x);        
            printf("addresses of a struct object next     : %p \n", (void*)&new -> next);
            printf("Data of a struct object 1             : %d \n", (void*)new -> x);
            printf("Data of a struct object 2             : %p \n", (void*)new -> next);    
        
        }
        
        return 0;
    }
    When I compile code I get following output

    addresses of a struct variable new : 0061FF1C
    addresses of a struct object x : 00750D18
    addresses of a struct object next : 00750D1C
    Data of a struct object 1 : 1
    Data of a struct object 2 : 00000000

    i don't understand why the address of a struct variable new and addresses of a struct object next are the same

    Can anyone explain why these two address are same ?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Huh?
    0061FF1C != 00750D1C
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2022
    Posts
    73
    Quote Originally Posted by Salem View Post
    Huh?
    0061FF1C != 00750D1C
    sorry I posted wrong code earlier
    Here is original code
    Code:
     #include <stdio.h>
    
    #include <stdlib.h>
     
     
    struct point 
    {
        int x;
         
        struct point *next; 
    };
     
     
    int main ()
    {
        struct point *new = NULL; 
         
        new = malloc (sizeof(*new));
         
         
        if ( new != NULL)
        {
             
            new -> x = 1;
      
            new -> next = NULL;
            printf("addresses of a struct variable new    : %p \n", (void*)&new);
    		printf("value of a struct variable new        : %p \n", (void*)new);
            printf("addresses of a struct object x        : %p \n", (void*)&new -> x);        
            printf("addresses of a struct object next     : %p \n", (void*)&new -> next);
            printf("Data of a struct object 1             : %d \n", (void*)new -> x);
            printf("Data of a struct object 2             : %p \n", (void*)new -> next);    
         
        }
         
        return 0;
    }
    addresses of a struct variable new : 0061FF1C
    value of a struct variable new : 00640D18
    addresses of a struct object x : 00640D18
    addresses of a struct object next : 00640D1C
    Data of a struct object 1 : 1
    Data of a struct object 2 : 00000000

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    A simpler example.
    Code:
    struct point p;
    printf("addresses of a struct : %p \n", (void*)&p);
    printf("addresses of first member : %p \n", (void*)&p.x);
    The first member of a struct always begins at the start of the structure.
    So naturally, a pointer to one is the same (numerically) as a pointer to the other.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    103
    Maybe this is being picky... But shouldn't the allocation size be explicit?

    Code:
    new = malloc (sizeof(struct point));
    and not

    Code:
    new = malloc (sizeof(*new));

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    G4143, it's the same thing.

    Actually, p = malloc(sizeof(*p)) is somewhat preferred:
    - it's one less thing to worry about as the compiler is doing all the work. Change the type of p, and you're still good on the malloc front.
    - if you wrap malloc in a macro, then that macro only needs one parameter (the variable) and not two (the variable and the type).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    103
    I just find it more 'self-documenting' when its explicitly stated what you are allocating.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Unfortunately, since new does not necessarily have a size of sizeof(struct point) bytes unless you've checked its declaration to confirm, it isn't as self-documenting as using sizeof(*new), in which it is clear that you intend the allocation to be for an object of the type of an object that new would point to.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Some comments to complement what Salem and laserlight said:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct point
    {
      int x;
      struct point *next;
    };
    
    int main ()
    {
      // 'new' object will be allocated on stack because
      // you are getting it's address later ('&new').
      // No need, here, to initialize it to NULL, since malloc() will do,
      // if failure occurs.
      struct point *new;
    
      // Notice sizeof has 2 syntaxes:
      //    'sizeof object' or 'sizeof(type|object)'
      // Since 'new' points to an object of 'struct point' type,
      // 'sizeof *new' is equivalent to 'sizeof(struct point)', in this case.
      new = malloc ( sizeof *new );
    
      if ( new == NULL )
        return EXIT_FAILURE;
    
      // Just to put some values in the allocated structure.
      new->x = 1;
      new->next = NULL;
    
      // OBS: You don't need to cast the pointers to 'void *'.
      // printf's '%p' format specifier need to get an 'void *' argument,
      // but all pointers are compatible to 'void *'.
    
      // '&new' will result in the address of 'new', not the address of the object allocated by malloc.
      printf ( "addresses of a struct pointer variable new : %p \n", &new );
    
      // 'new' contains the address of the object, as returned by malloc.
      printf ( "value of a struct pointer variable new     : %p \n", new );
    
      // The first element of the structure has the same address returned by malloc!
      printf ( "addresses of a struct object x             : %p \n", &new->x );
    
      // This address is sizeof(int) bytes ahead of the address returned by malloc.
      // But this can be 4 bytes ahead or 8 bytes ahead due to alignment.
      // ISO 9899 6.7.2.1 § 12 states each non-bitfield members alignment is
      // implementation defined. For x86-64 a pointer can be aligned by QWORD (8 bytes).
      printf ( "addresses of a struct object pointer next  : %p \n", &new->next );
    
      printf ( "Data of a struct object x                  : %d \n", new->x );
      printf ( "Data of a struct object new                : %p \n", new->next );
    
      return EXIT_SUCCESS;
    }
    Code:
    $ cc -o test test.c
    $ ./test
    addresses of a struct pointer variable new : 0xffffcc28
    value of a struct pointer variable new     : 0x800000440
    addresses of a struct object x             : 0x800000440
    addresses of a struct object pointer next  : 0x800000448
    Data of a struct object x                  : 1
    Data of a struct object new                : 0x0
    Here, 0xffffcc28 points to the stack. 0x800000440 is the beginning of the memory block allocated by malloc. Notice new and &new->x are the same value. The address of new->next starts 8 bytes after the beginning of the block allocated because the compiler aligned next to a QWORD boundary, in this case, for x86-64 mode. This can be different to i386 mode or other processors.

    []s
    Fred
    Last edited by flp1969; 02-21-2022 at 09:52 AM.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
      // OBS: You don't need to cast the pointers to 'void *'.
      // printf's '%p' format specifier need to get an 'void *' argument,
      // but all pointers are compatible to 'void *'.
    Ah, but you do have to cast %p pointers to void* (or at least you should).

    Arguments which match against ... in variadic functions undergo default promotion rules, not promotion according to the function prototype.
    But there is no promotion rule to magically transform T* to void*.

    So if you have an odd machine where T* and void* are represented differently, %p would likely produce garbage.

    > but all pointers are compatible to 'void *'.
    Whilst this is true, it's only implicit for round-trip assignment.
    T* assigned to void* assigned to T*

    If something wants a void*, but there isn't the information to coerce a void*, then you need to cast it yourself.

    Another example where this is necessary are the execl functions.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Salem View Post
    Ah, but you do have to cast %p pointers to void* (or at least you should).

    Arguments which match against ... in variadic functions undergo default promotion rules, not promotion according to the function prototype.
    But there is no promotion rule to magically transform T* to void*.
    Hummm... I agree, void * is compatible to all other types of pointers (ISO 9899 6.3.2.3 § 1), but this isn't the same of saying that all other pointers are the same as void *. So, yep... those pointers should be casted to void *.

    Thanks for the reminder, Salem.

    []s
    Fred

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 9
    Last Post: 11-09-2019, 05:37 AM
  2. Replies: 10
    Last Post: 07-10-2012, 04:28 AM
  3. Why does this structure allocate memory?
    By sanddune008 in forum C Programming
    Replies: 18
    Last Post: 07-14-2009, 07:31 AM
  4. Allocate a variable at a specific address
    By mermaidsrule in forum C Programming
    Replies: 11
    Last Post: 05-03-2007, 05:25 AM
  5. dynamically allocate a structure
    By dgraver01 in forum C Programming
    Replies: 3
    Last Post: 07-11-2002, 02:23 PM

Tags for this Thread