How exactly does const* char work?

Why, exactly, does code like the following work?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  #include <iostream>

struct Candybar
{
  const char* name;
  double weight;
  int calories;
};

int main()
{
  Candybar snack = { "Mocha Munch", 2.3, 350 };

  std::cout << "Snack: " << snack.name << "; Weight: " << snack.weight << "; calories: " << snack.calories << std::endl;

  return 0;
}


First, is it valid code? And if so, how does the compiler handle it in a valid way? Clearly pointer-to-const-char (const char*) only allocates enough memory for the pointer, but not the information it's pointing to, yet the program runs fine. Conceptually, I'd imagine, because the program doesn't define how much memory should be allocated for the data to which the pointer points, "Mocha Munch" is being written to unallocated memory; but I vaguely recall somewhere that string literals are converted to const char*, but I'm not sure.
String literals have their own immutable space allocated.
This means they are const, should never be deleted and are safe to use with const char*'s.
First, is it valid code?


Yes.

And if so, how does the compiler handle it in a valid way?


String literals are handled specially. They can't really be stored in the actual assembly instructions the way numeric literals are -- so they have to be stored in a separate segment of the exe.

Ultimately, the compiler will take all string literals that exist in your code, and clump them all together in a block of memory, keeping track of which string is where. Then, when you use one of those literals in your code, it will replace the literal with a pointer to wherever it put the actual string data.



So yes, you are correct in that const char* foo = "bar"; only allocates enough memory for the pointer. And what it actually points to is the segment of memory in the loaded .exe that the literal was placed.



On a side note, this is why you must always use a const char* when pointing to literals, and not simply a non-const char*. Since, when you are pointing to a literal.... the memory you're pointing to is not modifiable because it's part of the executable program, and not part of allotted heap/stack RAM. And therefore if you try to modify it you will have very bad things happen (typically an access violation/crash).


EDIT: Ninja'd by SGH's much more concise explanation.
Last edited on
This always trips me up, so I thought I'd ask so I had a reference at a later time. Thanks for both of your answers; both very helpful.
Topic archived. No new replies allowed.