Rick C. Hodgin said:
glen herrmannsfeldt said:
(snip)
char foo[] = "Rick"; // Goes to read-write memory
char* list[] = { "Rick" } // Goes to read-only memory
I want a way for list[0] to go to the same place as foo.
I am using Visual C++ compiler, but I am writing in C.
I use the C++ compiler because it has some relaxed syntax
constraints.
As I remember it, not having looked recently, the pre-ANSI (K&R)
compilers allowed writable strings. While not the best practice,
it was an allowed and sometimes useful technique.
All versions of the C language, from K&R to ISO C11, have permitted
compilers to make string literals writable. What's changed over
time is that most compilers don't take advantage of that permission.
Ah! That's a shame.
Not really, at least not for the vast majority of C programmers.
C string literals are intended to be *constant*. The fact that
compilers are permitted to generate code that crashes on an attempt to
modify the array specified by a string literal makes for better error
checking. The fact that such checks are not required is for backwards
compability for code written before the "const" keyword was added to the
language; even if not for that, C tends to make such things undefined
behavior rather than requiring run-time diagnostics.
[...]
I believe the language should operate such that as I've defined a to
point to "foo", and b to point to "foo", and these are separate
strings, then they should be separate strings in memory, the same as
if I'd said char* a="123"; char* b="456".
If *I* write
char *a = "foo";
char *b = "foo";
all I care about is that both a and b point to strings containing
the characters 'f', 'o', and 'o', in that order. (It also means
that I've forgotten the "const" keyword for some reason.) And if
I later write:
printf("%s\n", a);
the compiler is free to generate code that does the equivalent of
puts("foo");
Forbidding the two occurrences of "foo" to occupy the same memory
location would matter only if (a) you want to be able to modify the
contents of the array (which C doesn't permit you to rely on), or
(b) if you care about the result of (a == b).
If you want writable strings, you can get them:
char a_array[] = "foo";
char *a = a_array; /* or &a_array[0] */
It's slightly less convenient for what you're trying to do, but I don't
think that's a common enough case to justify changing the language as
you suggest.
A compatible language change (or compiler-specific extension) that
wouldn't break existing code might be a new kind of string literal, with
a prefix indicating that the array is writable and may not be shared
with other string literals with the same value. Perhaps something like:
char *a = W"foo";
char *b = W"foo";
a[0] = 'F';
printf("%s%s\n", a, b); /* will print "Foofoo" */
If you wanted to take that approach, you options would be:
1. Modify some open-source compiler to implement it as a language
extension (lots of work);
2. Persuade the maintainers of some compiler to provide it (less work
for you, but likely to fail); or
3. Persuade the ISO C committee to add such a feature to the next C
standard (even more likely to fail, and requries waiting at least a
decade before you can use it).
Barring that, you can either use the existing features of the language,
or implement a preprocessing step that translates code using something
like this feature into standard C.
BTW, you might find that compound literals (added to the language by the
1999 standard) are helpful:
This:
#include <stdio.h>
int main(void) {
char *s = (char[]){"hello"};
s[0] = 'H';
puts(s);
}
prints "Hello". But the array whose first element s points to is still
just 6 characters long, and unlike string literals, an object created by
a compound has automatic storage duration (it ceases to exist when you
leave the enclosing block).