Modify Static Data Okay?

D

Dave Vandervies

Is it legit to modify static data like the following code?

struct tbl {
int i;
char *s;
};

struct tbl t[] = {
{ 10, "hello" },
{ 12, "yoyoyoyoyoyoyoyoyoyo" }
}; [inside a function]
t[0].s = "something else"; /* modify the static table in place */


Yes. Unless it's const-qualified or a string literal, static data
is always writeable.

Note that the pointers you initialize t[].s with are pointing at string
literals, so you'd have to point them at something writeable before
you're allowed to write through them.


dave
 
M

Michael B Allen

Is it legit to modify static data like the following code?

#include <stdlib.h>
#include <stdio.h>

struct tbl {
int i;
char *s;
};

struct tbl t[] = {
{ 10, "hello" },
{ 12, "yoyoyoyoyoyoyoyoyoyo" }
};

int
main(void)
{
t[0].s = "something else"; /* modify the static table in place */

printf("%d %s\n", t[0].i, t[0].s);

return EXIT_SUCCESS;
}

Mike
 
M

Michael B Allen

struct tbl t[] = {
{ 10, "hello" },
{ 12, "yoyoyoyoyoyoyoyoyoyo" }
}; [inside a function]
t[0].s = "something else"; /* modify the static table in place */


Yes. Unless it's const-qualified or a string literal, static data is
always writeable.

Okay. Thanks.
Note that the pointers you initialize t[].s with are pointing at string
literals, so you'd have to point them at something writeable before
you're allowed to write through them.

Sure. I'm only talking about modifying the pointer. Actually in truth
I'm just adding a constant to the first int member of each element.

Thanks,
Mike
 
B

Barry Schwarz

Is it legit to modify static data like the following code?

Your code does not modify static data.
#include <stdlib.h>
#include <stdio.h>

struct tbl {
int i;
char *s;
};

struct tbl t[] = {
{ 10, "hello" },
{ 12, "yoyoyoyoyoyoyoyoyoyo" }
};

int
main(void)
{
t[0].s = "something else"; /* modify the static table in place */

This does not modify the "hello". It only modifies t[0].s so that it
points to a different location in memory.

If you had used strcpy, e.g.,
strcpy(t[0].s,"something else");
then you would have attempted to modify the "hello". This would
invoke undefined behavior, not because anything is static but because
attempting to modify a string literal is specifically described as
invoking undefined behavior.
printf("%d %s\n", t[0].i, t[0].s);

return EXIT_SUCCESS;
}

The static keyword describes the life of an object, not whether it is
modifiable. The two attributes are unrelated. Modifying a static
object is not a problem. Modifying a const object is a violation. As
noted above, modifying certain non-const objects (such as string
literals) is also a violation.


<<Remove the del for email>>
 
S

Stuart Gerchick

Michael B Allen said:
Is it legit to modify static data like the following code?

#include <stdlib.h>
#include <stdio.h>

struct tbl {
int i;
char *s;
};

struct tbl t[] = {
{ 10, "hello" },
{ 12, "yoyoyoyoyoyoyoyoyoyo" }
};

int
main(void)
{
t[0].s = "something else"; /* modify the static table in place */

printf("%d %s\n", t[0].i, t[0].s);

return EXIT_SUCCESS;
}

Mike

This is static, not const. You can modify a static variable as much
as you like. Static is how long the variable lives. Now you are not
really modifying the string literal, that you cant do. But pointing
the pointer elsewhere in your example.
 
B

bd

Barry said:
Your code does not modify static data.

Yes it does, but it is legal.
#include <stdlib.h>
#include <stdio.h>

struct tbl {
int i;
char *s;
};

struct tbl t[] = {
{ 10, "hello" },
{ 12, "yoyoyoyoyoyoyoyoyoyo" }
};

int
main(void)
{
t[0].s = "something else"; /* modify the static table in place */

This does not modify the "hello". It only modifies t[0].s so that it
points to a different location in memory.

t[] has static storage duration. It is legal to modify it however.
 
M

Method Man

[snip]
As
noted above, modifying certain non-const objects (such as string
literals) is also a violation.

I always considered string literals as constant objects. Why are they
considered non-const if they can not be modified? Is it because they're
stored in a different area of memory than const objects?
 
M

Michael Mair

Method said:
[snip]
As
noted above, modifying certain non-const objects (such as string
literals) is also a violation.

I always considered string literals as constant objects. Why are they
considered non-const if they can not be modified? Is it because they're
stored in a different area of memory than const objects?

It is because the standard people could not make their mind up ;-)
The thing is that the string literals were there before
the const qualifier, so there is as always the problem with
existing code.
Only const qualified things are "constant", so string literals are
not constant. However, you cannot modify them. So, if you want to
be on the safe side, you can point only pointers to const char at
them in order to make sure that you do not incidentally abuse the
pointer to try writing access, that is
const char *sptr = "Hello, ";
but still
char sarr[] = "world!\n";


Cheers
Michael
 
M

Mark McIntyre

I always considered string literals as constant objects. Why are they
considered non-const if they can not be modified?

"const" is a keyword with specific meaning. It does not mean constant. A
const object is a variable which you indicate to the compiler you don't
intend to modify. It is however still possible to do so via various tricks.
AFAIK the only true constants you can have in C are literals.
Is it because they're
stored in a different area of memory than const objects?

Possibly this might be done for efficiency reasons but the C Standard
doesn't specify where objects are stored.
 
C

Chris Torek

I always considered string literals as constant objects. Why are they
considered non-const if they can not be modified? Is it because they're
stored in a different area of memory than const objects?

String-literal-created arrays are in principle read-only, yes.
(Whether they are in fact read-only on any given implementation is
up to the implementation. Making them physically read-only usually
requires some kind of hardware level protection, whether it be in
the form of ROM, or page-protection, or similar; so systems without
such protection, or on which protections have been disabled for
some reason, the arrays will generally be write-able anyway.)

Now, given that "const" in C means, more or less, "read-only", I
suspect you mean to ask:

The array created by the string literal "hello" has type
"array 6 of char" instead of "array 6 of const char". Why?

The answer is, essentially, "history". Early C (before the original
1989 ANSI standard) had no "const" keyword, and hence no const-
qualified types. This meant that string-literal-created arrays
were *always* used with non-qualified pointers:

char *p = "hello";

The X3J11 (ANSI C) committee folks did not want to break existing
code, but did want to require "const" in cases like this:

const char s[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };
const char *p = s;

The only way to reconcile these two desires was to make string
literals produce arrays of type "array N of char" instead of "array
N of const char".

(I always thought -- and in fact still do think -- that they should
instead have given up on the second desire, and not made "const" a
type qualifier at all, but rather merely a storage-class modifier.
This would avoid the "const char *const *argv" problem:

char **argv;
...
const char *const *p = argv; /* must draw diagnostic in C */

This particular problem is fixed in a different way in C++, and C
could adopt the C++ rules; but note that C++ already makes the
arrays produced by string literals have type "const char [N]", too.
C and C++ are sufficiently different languages that it is often
not a good idea to move concepts between them casually.)
 
B

Barry Schwarz

[snip]
As
noted above, modifying certain non-const objects (such as string
literals) is also a violation.

I always considered string literals as constant objects. Why are they
considered non-const if they can not be modified? Is it because they're
stored in a different area of memory than const objects?
Before the const modifier was part of the language, a lot of code
contained statements of the form
char *x = "string";

If the string literal were of const type, this would no longer be
valid. Consider the case now of
const char *x1 = "string";
char *x2;
x2 = x1;

Rather than break a lot of previous code, actually rather than face a
commercial revolt, the standards committee elected to accept the
existing code. The fact that modifying a string literal invoked
undefined behavior then became a legal provision in the standard
rather than something the compiler could be required to enforce with a
diagnostic, much the same as i = i++.


<<Remove the del for email>>
 
K

Kenny McCormack

"const" is a keyword with specific meaning. It does not mean constant. A

And "static" doesn't mean "unchangeable".

(Amusing how those two misconceptions have run through this thread)
 
D

Dan Pop

In said:
The X3J11 (ANSI C) committee folks did not want to break existing
code,

Of course they did want to break existing code, but they wanted to break
it *silently*. That's why they wrote:

6 It is unspecified whether these arrays are distinct provided
their elements have the appropriate values. If the program
attempts to modify such an array, the behavior is undefined.

In K&R C, each string literal generates a unique array, this merging of
the string literals is an ANSI C feature.

Dan
 

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

Forum statistics

Threads
474,151
Messages
2,570,854
Members
47,394
Latest member
Olekdev

Latest Threads

Top