To make my sketches more readable, I usually declare constants (even if they are the same value) with different names. For example for a simple error code and sensor reset reason indication:
I'm not really familiar with the low level stuff, but I'm curious how these constants are stored. They will be stored in flash and loaded to register(s) from there, if needed? Constants with the same value will be stored only once?
Only the values are stored. The exact storage method depends on the machine architecture and the compiler. Optimization such as re-use of identical values is compiler dependent. 8 bit constants (on a machine with an 8 bit data bus) are often embedded in the machine code, inline, using "immediate" addressing modes. Sometimes called "literal".
Constants that are too big to fit in a machine instruction are allocated a place in memory and referenced with a memory address. Whether that is in ROM or RAM is machine dependent.
Usually, but it is compiler dependent. Optimization is not guaranteed by the language specification. Variables declared as constant, are not the same thing as literal values in expressions.
The ability to inline code a multi word constant in order to optimize some statement, depends on how that constant is used in the statement.
Inlining single word constants is so easy that it's been done almost since the beginning of C compilers. That's because it usually has processor support. That would apply to either declared or literal values of the same word size as the processor in question.
Distinction is between what you can commonly expect, and what is actually guaranteed.
Difference would depend on how literals are handled vs. variables. Since the #define is just a text replacement, you are somewhere doing something like
x = 123
vs.
x = Constant
Which could affect how optimization is performed, since it would use different underlying mechanisms.
There can't be any clarification. That is my point. Optimization is not guaranteed or defined. A "good" optimizer will translate
x = Constant
into
x = 123
All it has done, is convert a constant into a literal value.
but you can't make a general statement about that, except that "usually" it will. If it has to perform operations that require multi words, varying contexts would dictate different manipulation of the component words. An "old school" compiler would:
Allocate ROM memory for the declared constant
emit a macro for operations using its multi word value
Of course, they are much better than that now. But it's not guaranteed.
At the processor level, not all machine instructions are ambivalent about whether the data is variable or constant. Thus different code must be produced depending on which elements of an expression are literals or variables (taking it as a given that literals and constants are interchangeable).
Attempting to address your point directly, regardless of whether a contant replaced by a literal or a literal is involved, the compiler must allocate storage for it, if it is not possible to code it inline in machine code. Sometimes it is, sometimes it isn't. This, for example, can not be inlined: