Read-only string

V

v4vijayakumar

why the following string, 'str' is read-only?

char *str = "test string";

anyhow 'str' needs to be in memory. do you think, making 'str' red-only
would gain performance? or, it is right?
 
V

Vladimir Oka

v4vijayakumar said:
why the following string, 'str' is read-only?

char *str = "test string";

anyhow 'str' needs to be in memory. do you think, making 'str' red-only
would gain performance? or, it is right?

Character pointer `str` is /not/ read-only. You are free to assign any
other character pointer value to it. What /is/ read-only is the string
literal somewhere in memory to which `str` points.

One reason for this is that it enables embedded applications to put the
string literal into (physically) read-only memory. This may or may not
gain performance, but certainly saves RAM which in these systems tends
to command a price premium.
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

v4vijayakumar said:
why the following string, 'str' is read-only?

Because the C standard says so.
(well, it says it's undefined behavior to modify a string
literal)
char *str = "test string";

anyhow 'str' needs to be in memory. do you think, making 'str' red-only
str is not the same thing as "test string", str can be modified :)
 
M

Marc Boyer

Le 21-06-2006 said:
why the following string, 'str' is read-only?

char *str = "test string";

Because that is the way the langage is defined ?
You could wonder why the langage is designed this way.
I was not there, but my few knoledges in compilation let
me assume that, for some compiler, it was easier to do
so (it allow to store it in read-only memory).

Marc Boyer
 
V

v4vijayakumar

Vladimir said:
Character pointer `str` is /not/ read-only. You are free to assign any
other character pointer value to it. What /is/ read-only is the string
literal somewhere in memory to which `str` points.

One reason for this is that it enables embedded applications to put the
string literal into (physically) read-only memory. This may or may not
gain performance, but certainly saves RAM which in these systems tends
to command a price premium.


saving RAM?! anyhow still, you have to have these 12 bytes in RAM.
 
V

v4vijayakumar

Marc said:
Because that is the way the langage is defined ?
You could wonder why the langage is designed this way.
I was not there, but my few knoledges in compilation let
me assume that, for some compiler, it was easier to do
so (it allow to store it in read-only memory).

Marc Boyer


shouldn't it be the other way? it should be easier to programmers.
 
M

Marc Boyer

Le 21-06-2006 said:
shouldn't it be the other way? it should be easier to programmers.

You could not expect C to be an 'universal' langage,
to find a C compiler for every platform *and* to require
too many things from the compiler.
So, yes, the C langage does not requires behaviors
that would be too hard/costly to implement (like a stop
of the program when dereferencing null pointer for
example, or out-of-bound array acces).

Marc Boyer
 
R

Richard Bos

v4vijayakumar said:
saving RAM?!

In embedded devices, yes, why not? In large programs on a PC, yes, why
not, if the string isn't "test string" but a 2000-entry array of
200-character strings?
anyhow still, you have to have these 12 bytes in RAM.

Says who? You put them in ROM, of course. ROM is often cheaper than RAM.
In "normal" programs, you can put them in the executable image, save
some superfluous string copying, and eliminate duplicates.

Richard
 
R

Richard Bos

v4vijayakumar said:
shouldn't it be the other way? it should be easier to programmers.

Why would it be easier for programmers? You can get the behaviour you
want using

char str[] = "test string";

and the efficient behaviour using

char *str = "test string";

Choice is good. Catering to stupid hack programmers is not good.

Richard
 
M

Marc Thrun

v4vijayakumar said:
saving RAM?! anyhow still, you have to have these 12 bytes in RAM.

No, they can safely be placed into ROM, as the compiler can assume that
you will never modify the string literal. If you do so, you invoke
undefined behaviour, so the compiler is not responsible for this. If you
want a modifiable string, use the string literal as an initializer for
an array:

char str[] = "test string";
 
V

Vladimir Oka

v4vijayakumar said:
saving RAM?!

RAM in your mobile phone ("cell" if you're on the other side of the
pond), to give one example, can command a price premium compared to
other types of memory used in it (mainly Flash). Being generally
faster, it can also be better used for time critical task (reading
constant strings is rarely such a task).

The fact that PC RAM and HDD space is (comapratively) cheap these days
is irrelevant to that particular market segment. Don't be blinded by
the obvious.
anyhow still, you have to have these 12 bytes in RAM.

Why, if you care to explain?

Yes, if you want to modify them, but then you're going about it the
wrong way. At least in C.
 
V

Vladimir Oka

v4vijayakumar said:
shouldn't it be the other way? it should be easier to programmers.

But it is! It makes it easy for me to create cost/performance efficient
designs.

It also makes it easy for you, if you care to study language enough to
come across use of character arrays:

char str[] = "hello, world";
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

v4vijayakumar said:
saving RAM?! anyhow still, you have to have these 12 bytes in RAM.

Imagine an application with a lot of strings (my linux shell /bin/bash
seems to have almost 50KiB of text!).
Placing these strings in a read only "segment" can allow OSs to share
that part among multiple running instances of the application.
And it allows merging of strings too, ("World" and "Hello World" might
need just a 12 bytes of storage for those 2 strings + the pointers to
them) save a bit here and there , it might add up.
 
K

Kenneth Brody

Vladimir said:
v4vijayakumar wrote: [...]
char *str = "test string";
[...]
shouldn't it be the other way? it should be easier to programmers.

But it is! It makes it easy for me to create cost/performance efficient
designs.

It also makes it easy for you, if you care to study language enough to
come across use of character arrays:

char str[] = "hello, world";

And things like this can lay in hiding in a program for years, or
even decades. Literally!

I had written code, back in the early 1980's, which included the
equivalent of:

char *filename = "foo.xxx";

...

strcpy(filename+4,"bar");

This "worked" until sometime in the 1990's, when the program was
ported to a system which actually did place "foo.xxx" into a read-
only memory segment. (Note that it was still in RAM. It's just
that the hardware and O/S supported marking some pages of memory
as "read-only data".)

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Kenneth Brody

:
[...]
And it allows merging of strings too, ("World" and "Hello World" might
need just a 12 bytes of storage for those 2 strings + the pointers to
them) save a bit here and there , it might add up.

I assume that it could also merge "Hello" and "Hello World", _if_ the
"Hello" were defined without the trailing nul?

Now, how does one define a pointer to 5 chars?

cdecl says:

cdecl> explain char (*foo)[5];
declare foo as pointer to array 5 of char

but gcc complaint on this:

char (*foo)[5] = "Hello";

with:

foo.c:1: warning: initialization from incompatible pointer type

At first, I thought that's because "Hello" is actually an array of 6
chars, but changing it to "1234" gives the same error.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
R

Richard Heathfield

Kenneth Brody said:
:
[...]
And it allows merging of strings too, ("World" and "Hello World" might
need just a 12 bytes of storage for those 2 strings + the pointers to
them) save a bit here and there , it might add up.

I assume that it could also merge "Hello" and "Hello World", _if_ the
"Hello" were defined without the trailing nul?

Now, how does one define a pointer to 5 chars?

cdecl says:

cdecl> explain char (*foo)[5];
declare foo as pointer to array 5 of char
Yes.


but gcc complaint on this:

char (*foo)[5] = "Hello";

Yes, because char (*)[5] is not the same as char * (which is what you get
when you evaluate a char[6] such as "Hello").

This works, though:

char bar[5] = "Hello"; /* caveat - bar does not contain a string */
char (*foo)[5] = &bar;
 
A

Andrew Poelstra

why the following string, 'str' is read-only?

char *str = "test string";

anyhow 'str' needs to be in memory. do you think, making 'str' red-only
would gain performance? or, it is right?

Well, being as the compiler is allowed to put "test string" wherever it
wants, it could elect to put it within the executable code.

Now, an OS will likely not allow programs to modify executable code,
because that will make it too easy to create viruses. Therefore,
strings store in executable code are not modifiable.


That should be enough of an example for you; for others, read the rest
of the thread.
 
K

Keith Thompson

v4vijayakumar said:
shouldn't it be the other way? it should be easier to programmers.

Easier to do what?

If strings are writable, then this program:
========================================
#include <stdio.h>
#include <string.h>

static void print_string(char *s)
{
puts(s);
strcpy(s, "xxxxx");
}

int main(void)
{
int i;
for (i = 0; i < 2; i ++) {
print_string("Hello");
}
return 0;
}
========================================
will produce this output:
========================================
Hello
xxxxx
========================================

It's easy enough to do this if it's what you want. By preventing you
from modifying string literals, the implementation is, in a small way,
preventing you from shooting yourself in the foot.
 
C

Chris Torek

Kenneth Brody said:
... but gcc complaint on this:
char (*foo)[5] = "Hello";

Yes, because char (*)[5] is not the same as char * (which is what you get
when you evaluate a char[6] such as "Hello").

This works, though:

char bar[5] = "Hello"; /* caveat - bar does not contain a string */
char (*foo)[5] = &bar;

Note that you can also write:

char (*p0)[5] = &"1234";

If you want a non-string, you must either use the method Richard
Heathfield showed above, or the newfangled C99 compound-literals:

char (*p1)[5] = &(char []){'H', 'e', 'l', 'l', 'o'};
char (*p2)[5] = &(char [5]){"Hello"};

The size of the array can be omitted only in the initializer for
p1, in this case.

(Sure would be nice if C89 had allowed one to write "Hello\z"
to suppress the trailing \0, instead of making up a silly rule for
array initializers with specified sizes. :) )
 
M

Mark McIntyre

(of readonly data)
saving RAM?! anyhow still, you have to have these 12 bytes in RAM.

No, you could burn it into ROM or an EEPROM or whatever. This is in
fact what many embedded systems do. Consider the BIOS in your
computer.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,973
Members
47,529
Latest member
JaclynShum

Latest Threads

Top