- The first paragraph says that "a literal in C denotes a fixed value".
- Does it mean that a literal (except compound literals) shouldn't be modified?
I don't know what the authors intention was, but modification of the array resulting from a string literal during runtime is blatantly undefined, according to C11/6.4.5p7: "If the program attempts to modify such an array, the behavior is undefined."
It should also be noted that attempts to modify a const
-qualified compound literal during runtime will also result in undefined behavior, which is explained along-side some volatile
-related undefined behaviour in C11/6.7.3p6. It is otherwise well defined to modify compound literals.
For example:
char *fubar = "hello world";
(*fubar)++; // SQUARELY UNDEFINED BEHAVIOUR!
char *fubar = (char[]){"hello world"};
(*fubar)++; // This is well defined.
Literally replacing "hello world"
with "goodbye galaxy"
, in either piece of source code, is fine. Redefining standard functions, however (i.e. #define memcpy strncpy
or #define size_t signed char
, which are both great ways to ruin someone elses day), is undefined behaviour.
- Since a string literal isn't a compound literal, should a string literal be modified?
The array resulting from a string literal should certainly not be modified during runtime, for any attempt to do so would trigger undefined behaviour.
The string literal itself, which exists as a quoted sequence of characters within your source code, on the other hand... of course, that can be modified as you choose. You're not obliged to modify it, though.
The second paragraph says that "C does not strictly prohibit modifying string literals" while compilers do. So should a string literal be modified?
The C standard doesn't strictly prohibit a lot of undefined behavior; it leaves the behavior undefined, meaning your program is likely to behave erratically or be non-portable. In the realms of well defined C, your programs should not invoke any undefined behaviour, including overflowing arrays, modifying const
-qualified objects or the arrays resulting from string literals, race conditions caused by multithreading, etc.
If you want to invoke undefined behaviour, C will let you shoot yourself in the foot. You might have a good reason for doing so; perhaps your program will be more optimal, or perhaps your compiler actually lets you modify string literals ("it's a feature, not a bug", they say, "so give us your money", they say, as you become reliant upon their non-standard quirks). Be aware that some compilers will instead behave as though the attempted modification didn't occur, or crash, or there could be some vulnerability caused.
... and above all else, be aware that your code will no longer be compliant C code!
Do the two paragraphs contradict each other?
By omission, perhaps. The first paragraph does state that the values are fixed, and the second paragraph that the values might be modifiable during runtime through invocation of undefined behaviour.
I think the author meant to make the distinction between elements of source code and the runtime environment. He/she could simply clarify this by ensuring it's explicit that literals should not be modified during runtime, for example.
How shall I understand them?
In the realms of C such values can't change during runtime because invoking undefined behaviour means the code in question is no longer compliant C code.
Perhaps they were trying to avoid explaining undefined behaviour, because it may seem too complex to explain. If you look deeper into the subject, you'll find that the meaning is, as predicted, roughly a conjunction of the two words.
undefined: /ʌndɪˈfʌɪnd/ adj. not clear or defined.
behaviour: /bɪˈheɪvjə/ noun. the way in which a machine or natural phenomenon works or functions
That is to say, an attempt to modify the array resulting from a string literal during runtime results in "unclear functionality". It's not required to be documented anywhere in the realms of computer science, and even if it is documented, that documentation might be a lie.
Can a literal which is neither compound literal nor string literal be modified?
As a lexical element in source code, providing it doesn't override a standard symbol, yes. Literals which aren't l-values (i.e. don't have any storage) such as integer constants, obviously can't be modified during runtime. I suppose it might be possible on some systems to attempt to modify the memory which a function pointer points at, which could be seen as a literal; that's also undefined behaviour and would result in code that isn't C.
It might also be possible to modify many other types of elements which aren't seen as objects by the C standard, such as the return address on the stack. That's what makes buffer overflows so subtly dangerous!