0

I wonder where the literal string that str points to is allocated, given that (I assume) malloc only makes room for the pointer into the Heap.

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int a;
    char* str;
} Bar;

int main(int argc, char *argv[])
{
    Bar* bar_ptr = malloc(sizeof *bar_ptr);

    bar_ptr->a = 51;
    bar_ptr->str = "hello world!";

    printf("%d\n", bar_ptr->a);
    printf("%s\n", bar_ptr->str);

    free(bar_ptr);

    return 0;
}
aledruetta
  • 107
  • 1
  • 2
  • 8
  • 3
    The string `"hello world"` is stored in a read-only data segment, `bar_ptr->str` only points to that address. – bereal Nov 12 '22 at 15:47
  • 2
    You are correct that the struct contains only the pointer, not the array in which the characters of the string literal reside. But otherwise, I'm unsure what kind of answer you're looking for about where the string data are. The best answers that the language spec itself supports would be "somewhere else" and "where the pointer points". – John Bollinger Nov 12 '22 at 15:48
  • 1
    `"hello world!"` is a string literal. This is a null-terminated character string, typically stored in read-only memory and loaded into your address space when you run the program. `bar_ptr->str` points to it. – Tom Karzes Nov 12 '22 at 15:51
  • @JohnBollinger, I mean Heap, Stack or read-only memory segments. Now, after the answers, I understand that it is in somewhere static region. – aledruetta Nov 12 '22 at 16:55

2 Answers2

1

As already pointed out the string is stored in a read-only data segment. You can print the address where the string is stored (in hexadecimal format) like that:

printf("0x%p\n", bar_ptr->str);
  • to be 100% correct (pedantic?) [you should cast the address argument of `printf` to `void*`](https://stackoverflow.com/questions/30354097/how-to-printf-a-memory-address-in-c) – yano Nov 13 '22 at 04:09
1

Correct - all your struct type stores is the address of the first character in the string. The string contents are stored "somewhere else" - in a string literal, in another dynamically-allocated block, in a static or auto array, etc.

You could declare everything auto:

void foo( void )
{
  char aStr[] = "this is not a test";
  Bar barInstance;

  barInstance.a = 51;
  barInstance.str = aStr;

  ...
}

You could allocate everything dynamically:

Bar *barInstance = malloc( sizeof *barInstance );
if ( barInstance )
{
  size_t size = strlen( "This is not a test" );
  barInstance->str = malloc( size + 1 );
  if ( barInstance->str )
    strcpy ( barInstance->str, "This is not a test" );
  ...
  /**
   * You must free barInstance->str before freeing
   * barInstance - just freeing barInstance won't
   * free the memory barInstance->str points to,
   * since that was a separate allocation.
   */
  free( barInstance->str );
  free( barInstance );
}

** Edit **

And there are other possibilities, but the point is that the string itself is stored separately from the struct instance.

John Bode
  • 119,563
  • 19
  • 122
  • 198