>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.