>char *s = "Hello";
>s[0] = 'J';
puts(s);
might print "Jello" in a pre-ANSI compiler - is the behaviour of this
program undefined in any pre-ANSI compiler - or would it always have printed
"Jello" with a pre-ANSI compiler?
Since there is no pre-ANSI C standard, anything a pre-ANSI compiler
does is undefined.
>In gcc with the "writable-strings" option this program prints
Jello
There are no "compiler options" in ANSI C, there are only different
implementations. The number of combinations of such compiler options
can make the number of implementations enormous. In this case,
both "writable-strings" and non-"writable-strings" can conform to
ANSI C.
>If there were more than one semantics for what this progran did under a
pre-ANSI compiler, which semantics were chosen by gcc for the
"writable-strings" option, and for what reason?
The behaviors I know of in pre-ANSI compilers are (a) string literals
were put in writable storage, or (b) string literals were put in
non-writable storage (which might be RAM with memory management
protecting it). If a write was attempted to non-writable storage,
the behavior likely fell into two classes: (b1) the write was
ignored, or (b2) the write attempt caused some kind of CPU trap
which aborted the program or got mapped into a signal. Which of
(b1) or (b2) happened usually depended on hardware.
Even some compilers that did not implement non-writable-strings
could be compiled with a more complex (and system-specific) procedure
involving xstr which would preprocess the C and generate a big array
with the strings in it, and change the program to refer to that
array. That array was made read-only by, er, implementation-specific
magic.