Whether log.Name points to RAM or Flash after log.Name = "Literal"; , can actually be manipulated by the C linker, especially if using ELF-based tools. This is because string literals are stored in a specific ELF section, typically rodata.strx.y, and the linker can choose where it actually ends up; typically rodata.
What helius wrote above, matches basically all hosted environments (those where you write normal C application code).
In the Arduino environment, depending on the core (AVR or one of the 32-bit ARMs), one can change this easily. For example, log.Name = F("Literal"); ensures the string is in Flash, whereas normally log.Name = "Literal"; causes the string literal to be in RAM.
A better option is to use an enum ("enumeration constant") instead. For example,
typedef enum {
DATA_NAME_UNKNOWN = 0,
DATA_NAME_FOO,
DATA_NAME_BAR,
DATA_NAME_WHOTSITS,
DATA_NAME_NOMINAL,
DATA_NAME_ANIMAL,
DATA_NAME_IS,
DATA_NAME_STUPID,
DATA_NAME_ETC,
DATA_NAME_MAX = DATA_NAME_ETC
} data_name;
typedef int data_type;
struct data {
data_type count;
data_name name;
};
If you don't assign any specific values to the enums, the compiler will assign one in ascending order. In the code, they are equivalent to the integer constant values assigned to them. It is common to have the first one (or "invalid"/"unused" or similar) as zero, and a maximum as the last one, so that one can check if e.g. int i matches a known enum: if (i >= 0 && i <= DATA_NAME_MAX) { /* Within valid range */ } else { /* Outside valid range */ }.
Furthermore, if you use a variable of some enum type as the argument to switch(), most C compilers will warn you if you forget one of the constants (and do not have a default: case). Very useful, don't you agree?
In some C library code, you'll see enums defined thus:
enum {
FOO = 1,
#define FOO FOO
BAR,
#define BAR BAR
BAZ,
#define BAZ BAZ
};In C, enums are an integer type, and can be used in expressions without any explicit casts. The reason why one would define a preprocessor macro with the same name as an enum constant, is that that way, the library user can check if a constant is known via #if defined(BAR) ... #endif . This is very useful for modular portable code, which can check if features are available at compile time or not.