When you program your ATMega328, the entire program instructions, and any data it requires (initialisation data for variables, constants) is written into the flash memory (aka program memory)
When your code runs, the instructions are read from the flash memory, memory on the stack (ram) is allocated for the variables (inc "const" declared ones where applicable but they can be optimised to just "hardcode" by the compiler where it is beneficial) and the data is copied from the flash memory into that allocated stack to initialise your variables (& constants if applicable).
1Because of Harvard architecture, the running code can not *normally* access data in the flash memory, only in the ram.
You can however tell the compiler "look, really, you can just leave this thing in flash memory, don't allocate any memory on the stack for it, just give me the address in the program memory for it, I know I can't access it easily, but leave it there and I'll grab it only when I need it".
You do that using "PROGMEM" and the various functions available in avr-libc for accessing progmem stored data.
http://www.nongnu.org/avr-libc/user-manual/pgmspace.htmlhttp://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.htmlhttp://playground.arduino.cc/Main/PROGMEMhttp://www.arduino.cc/en/Reference/PROGMEMNote that in Arduinoland there is also the "F()" macro and "__FlashStringHelper" which is essentially an abstracted way of using PROGMEM for strings - provided the thing you are giving it to understands what to do with a __FlashStringHelper, which means it knows how to use PROGMEM stored data.
1 - Note here well, the initialisation data is stored in flash and copied to ram. If you have 'char *foo = "Hello World";' then Hello World is stored in flash, and copied into ram, taking equal memory in both places. Even if it's 'const char *foo' the compiler will almost certainly not do any on-the-fly shuttling between flash and ram for you, it will take memory in both places.