What determines whether a globally defined string is in the read-write or the read-only area of the data segment?

StackOverflow https://stackoverflow.com/questions/20460875

  •  30-08-2022
  •  | 
  •  

Question

From Wikipedia:

const char* string = "hello world" makes the string literal "hello world" to be stored in initialized read-only area and the character pointer variable string in initialized read-write area.

  1. Why is string stored in the read-write area when it was declared with the const modifier?
  2. Why is "hello world" stored in the read-only area when strings are supposed to be immutable?
  3. Is there a way to determine (in the code itself) in what segment and area a variable is stored (C99)?
  4. Why is there not a separation between read-only and read-write areas in the BSS/initialized data segment?
  5. Would the quoted statement above still be true if the const modifier was left off? If no, why not?
Was it helpful?

Solution

You're misunderstanding. The string is always read-only. The variable string that holds the pointer to the string is a mutable variable, so it must be reassignable:

const char * string = "abc";

int main()
{
    string = NULL;    // this must work
}

Moreover, you should appreciate that the C standard does not contain any requirements about implementation details of real programs, and in particular no notion of "read-only memory". It's purely a choice of the platform (compiler, linker, binary format, loader) whether they wish to provide distinct kinds of memory with different access permissions.

OTHER TIPS

I don't quite get what you are trying to ask. In your example the "hello world" is stored in the read-write area, but the pointer to it isn't, since it wasn't declared as const.

const char* string means, this is a mutable pointer to an constant string.

To cause the pointer being stored in the read-only area, too, you would have to declare it as const:

const char* const string = "hello world";

const

I general all modifiers in the C and C++ languages bind to the value to it's left. Only if there is nothing to the left, they apply to the next to their right. Hence these two are the same:

char const* str; // Bind const modifier to 'char'.
const char* str; // Bind const modifier to 'char', since there is nothing to the left.

When looking at this, you need to be aware of that a pointer declaration consists of 2 "parts". The type the pointer points to, and the pointer itself.

Modifiers like const or volatile can be applied to both of these parts:

char* const str; // A constant pointer, that points to a mutable char (array).

Here a few examples, how const affects variables:

char const* a = "foo";
*a = '\0';  // Error, the array pointed to is not mutable.
a = "bar";  // Okay.

char* const b = "foo";
*b = '\0';  // Okay.
b = "bar";  // Error, the pointer is not mutable.
  • Why is string stored in the read-write area when it was declared with the const modifier?

That is where all literal constants go. That way they can be shared among processes and among other pointers to them.

  • Why is "hello world" stored in the read-write area when strings are supposed to be immutable?

Pointer (to literal constant) itself is mutable. "hello world" is likely to be stored in global consts.

  • Is there a way to determine (in the code itself) in what segment and area a variable is stored (C99)?

Globals and statics go to 'globals', local vars and args go to 'stack', malloc'ed go to 'heap'. As for globals, those that are consts may or may not go to 'global consts'.

  • Why is there not a separation between read-only and read-write areas in the BSS/initialized data segment?

There are usually two segments - one for const data (and that one is shared between processes) and one for mutable data (which cannot be obviously shared).

  • Would the quoted statement above still be true if the const modifier was left off? If no, why not?

In C++ all string literal are const char*, while in C they are char* by nature. So, there is no problem to add/remove const from string variable in C (apart from warning sometimes), while it will cause const-cast error in C++. Having const in const char* string prohibits string's data from being modified.

P.S. The following code might help you to understand what is going on:

int main()
{
    char s1[] = "abc";
    char* s2  = "abc";
    const char* s3  = "abc";
    s1[0] = 'z';
    s2[0] = 'x';
    // s3[0] = 'y'; will not compile due to const
    printf("%s %s %s\n", s1, s2, s3);
    s2++; s3++; // it perfectly fine to modify pointers themselves
}

Depending on platform, the code might crash (Linux) at s2[0] assignment, or might succeed; in later case, s3 might get modified too (Cygwin) or might not.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top