Thread: Memory Layout of character pointers

  1. #1
    Registered User
    Join Date
    Aug 2019
    Posts
    3

    Memory Layout of character pointers

    Hi,

    I am trying to understand memory layout of pointers. Please see my source below:

    Program Source:

    Code:
    #include <stdio.h>
    
    int main (void) { 
    
    
        char *names[] = {"t", "th", "str"};
    
    
        printf("Base Address of names:%u\n", names); 
    
    
        for (int i = 0; i < 3; i++) { 
            printf("Base Address of string:%d: %u\n", i, names[i]);
        }
    
    
        return 0;
    
    
    }
    Program Output:
    Base Address of names:2791861872
    Base Address of string:0: 2858211288
    Base Address of string:1: 2858211290
    Base Address of string:2: 2858211293


    Questions:
    I can see that the base address of strings are right next to each other. However,

    Could you please explain why why the base address of names is nowhere close to the string[0]? What is wrong with my code?

    Thanks,
    Karthigan

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    3,675
    Because you are printing the value and not the address.

    names[i] // Value

    &names[i] // Address
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    533
    Quote Originally Posted by stahta01 View Post
    Because you are printing the value and not the address.

    names[i] // Value
    &names[i] // Address
    Nope... in this case 'names' is converted to a pointer and each element of the array is a pointer too...
    To print a pointer, use %p, not %u.

    More: There is no garantees where the compier will allocate the blocks of data, except for the individual string literals and the elements of array 'names' itself... In the example:
    Code:
    char *names[] = {  "t", "th", "str" };
    The blocks 't\0', 'th\0' and 'str\0' could be allocated out of sequence. In assembly, the compiler could choose to do something like this:
    Code:
    section .data
    str.names0:  db  't',0
    i:           dd 0
    str.names1:  db  't','h',0
    names:       dq  str.names0, str.names1, str.names2
    str.names2:  db  's', 't', 'r', 0
    Except for the fact that 'str.names0', 'str.names1' and str.names2' are allocated in a different segment (.rodata), but, disconsidering this detail, the choice, above is still valid.

    PS: Ok... i (if no otimizations were enabled) and names would be allocated on stack, but you get my point, don't ya?
    Last edited by flp1969; 08-13-2019 at 04:48 PM.

  4. #4
    Registered User
    Join Date
    Aug 2019
    Posts
    3
    Quote Originally Posted by flp1969 View Post
    Nope... in this case 'names' is converted to a pointer and each element of the array is a pointer too...
    To print a pointer, use %p, not %u.

    More: There is no garantees where the compier will allocate the blocks of data, except for the individual string literals and the elements of array 'names' itself... In the example:
    Code:
    char *names[] = {  "t", "th", "str" };
    The blocks 't\0', 'th\0' and 'str\0' could be allocated out of sequence. In assembly, the compiler could choose to do something like this:
    Code:
    section .data
    str.names0:  db  't',0
    i:           dd 0
    str.names1:  db  't','h',0
    names:       dq  str.names0, str.names1, str.names2
    str.names2:  db  's', 't', 'r', 0
    Except for the fact that 'str.names0', 'str.names1' and str.names2' are allocated in a different segment (.rodata), but, disconsidering this detail, the choice, above is still valid.

    PS: Ok... i (if no otimizations were enabled) and names would be allocated on stack, but you get my point, don't ya?
    Thank you for the detailed explanation! I used %p to print the pointer. And in this case, it is indeed continuous allocation - see output below:

    Base Address of names : 0x561e9e1737d8
    Base Address of string:0: 0x561e9e1737d8
    Base Address of string:1: 0x561e9e1737da
    Base Address of string:2: 0x561e9e1737dd

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    533
    Quote Originally Posted by karthigan View Post
    Thank you for the detailed explanation! I used %p to print the pointer. And in this case, it is indeed continuous allocation - see output below:

    Base Address of names : 0x561e9e1737d8
    Base Address of string:0: 0x561e9e1737d8
    Base Address of string:1: 0x561e9e1737da
    Base Address of string:2: 0x561e9e1737dd
    You're welcome.... But keep this in mind... it is not garanteed you got an sequential allocation, except for the array and individual string literals (which are pointers to arrays as well).

    If you need that kind of garantee you could do:
    Code:
    static char *s = "t\0th\0str";
    char *names[] = { s, s + 2, s + 5 };
    And you are, still, doing something wrong... 'names' is allocated on stack, and its elements on .rodata section. They have different addresses:
    Code:
    #include <stdio.h>
    
    int main( void )
    {
      int i;
      char *names[] = { "t", "th", "str" };
    
      printf( "%p\n", names );
    
      for ( i = 0; i < 3; i++)
        printf( "%p\n", names[i] );
    }
    Compiling and running (x86-64):
    Code:
    $ cc -O2 -o test test.c
    $ ./test
    0x7ffc1c0d7620
    0x55ff8695b804
    0x55ff8695b806
    0x55ff8695b809
    Notice the different address form of 'names' (the first value).
    Last edited by flp1969; 08-13-2019 at 05:37 PM.

  6. #6
    Registered User
    Join Date
    Feb 2019
    Posts
    533
    Maybe drawing makes easier to see why 'name' and each element from the 'name' array cannot share their addresses:

    Memory Layout of character pointers-untitled-png

    I'm not having fun at your expense here... drawing really helps a lot!
    Last edited by flp1969; 08-13-2019 at 05:59 PM.

  7. #7
    Registered User
    Join Date
    Aug 2019
    Posts
    3
    Quote Originally Posted by flp1969 View Post
    Maybe drawing makes easier to see why 'name' and each element from the 'name' array cannot share their addresses:

    Memory Layout of character pointers-untitled-png

    I'm not having fun at your expense here... drawing really helps a lot!
    Understood, thank you! I appreciate the detailed explanation again. I found the mistake in my code, fixed it, and my result now aligns with yours.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory layout of c program
    By sujji in forum C Programming
    Replies: 3
    Last Post: 10-15-2013, 12:08 AM
  2. Replies: 14
    Last Post: 10-12-2012, 02:39 AM
  3. memory layout??
    By ungainly_one in forum C Programming
    Replies: 14
    Last Post: 11-14-2010, 10:12 AM
  4. Memory Layout
    By chris.r in forum C Programming
    Replies: 5
    Last Post: 04-18-2010, 02:41 PM
  5. memory layout and declaration
    By cbastard in forum C Programming
    Replies: 6
    Last Post: 09-13-2005, 12:24 PM

Tags for this Thread