Search code examples
cstringpointersmemorystring-literals

How is array of string literal in C stored?


Take a look at following code and output:

char *words[] = {"wehrmarcht", "collectorate", "hello", "hello","precorrection", "hello","wehrmarcht"};
char *wp;
cnode *np;
for(wp = *words; wp - *words < sizeof(words); wp += strlen(wp) + 1) {
    printf("wp -> %s\n", wp);
}
printf("==============================================\n");
for(int i = 0; i < sizeof(words) / sizeof(char *); i++) {
    printf("words[%d] -> %s\n", i,words[i]);
}

output:

wp -> collectorate
wp -> precorrection
wp -> wp -> %s

wp -> ==============================================

==============================================
words[0] -> wehrmarcht
words[1] -> collectorate
words[2] -> hello
words[3] -> hello
words[4] -> precorrection
words[5] -> hello
words[6] -> wehrmarcht

Process finished with exit code 0

Can someone explain what makes the wp points to some strings in code? Thanks in advance.


Solution

  • In order to experiment, I just changed your example to display the addresses of the strings.
    You can see that we cannot make any assumption about the way each of these strings is stored relative to each other.

    On my system (Linux 64-bit) I obtain:

    $ ./prog_c
    words[0] @ 0x5631c83b6080 -> wehrmarcht
    words[1] @ 0x5631c83b60c0 -> collectorate
    words[2] @ 0x5631c83b6100 -> hello
    words[3] @ 0x5631c83b6100 -> hello
    words[4] @ 0x5631c83b6140 -> precorrection
    words[5] @ 0x5631c83b6100 -> hello
    words[6] @ 0x5631c83b6080 -> wehrmarcht
    
    /**
      gcc -std=c99 -o prog_c prog_c.c \
          -pedantic -Wall -Wextra -Wconversion \
          -Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
          -g -O0 -UNDEBUG -fsanitize=address,undefined
    **/
    
    #include <stdio.h>
    
    int
    main(void)
    {
      const char *words[]={"wehrmarcht", "collectorate", "hello", "hello", "precorrection", "hello", "wehrmarcht"};
      const int count=(int)(sizeof(words)/sizeof(words[0]));
      for(int i=0; i<count; ++i)
      {
        printf("words[%d] @ %p -> %s\n", i, (void *)words[i], words[i]);
      }
      return 0;
    }