0

I'm told that when initializing a string like so

char str[] = "Hello world!";

The compiler will allocate an area in constants memory(read only for the program) and then copy the string to the array which resides in the stack. My question is, can I read or point to the original string after modifying the copy I'm given, and how? And if not, why does the string even exist outside of the stack in the first place?

  • Well, how else is that data going to get into the correct place on the stack? – Oliver Charlesworth Jun 29 '14 at 15:57
  • 4
    Why do you want to do this? We can probably help if you tell us what your real requirement is. – Hogan Jun 29 '14 at 15:59
  • If `str` is not at block scope then it is not "in the stack". if it is at block scope and you never actually modify its contents, the compiler could optimize it out (and just refer directly to the string literal for reads). – M.M Jun 29 '14 at 16:36
  • [I remember a similar question a few days ago.](http://stackoverflow.com/questions/24018573/does-garbage-collection-happen-when-we-initialize-a-char-array-with-a-string-lit) – mafso Jun 29 '14 at 16:42
  • Regarding specific question: _can I read or point to the original string after modifying the copy I'm given, and how?_ ***see below***. – ryyker Jul 01 '14 at 17:07

5 Answers5

1

It's done this way for space efficiency. When you write:

char str[] = "Hello world!";

it's compiled effectively as if you'd written:

static char str_init[] = "Hello world!";
char str[13];
strncpy(str, str_init, 13);

An alternative way to implement this might be equivalent to:

char str[13];
str[0] = 'H';
str[1] = 'e';
 ...
str[11] = '!';
str[12] = 0;

But for long strings, this is very inefficient. Instead of 1 byte of static data for each character of the string, it will use a full word of instruction (probably 4 bytes, but maybe more on some architectures) for each character. This will quadruple the size of the initialization data unnecessarily.

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Because the program has to remember the string somewhere, i.e., your so-called "constant memory". Otherwise how can it know what values to assign when allocating the variable? Think about a variable with a given initial value. The variable is not allocated until declared. But the initial value must be stored somewhere else.

Neo1989
  • 285
  • 3
  • 14
  • Well, it _could_ compile it as if it were `char str[13];str[0] = 'H';str[1] = 'e'; ...; str[12] = 0;` – Barmar Jun 29 '14 at 16:19
0

When the program runs, "Hello world" will be stored in the constant part of the memory as a string literal, after that, the program will reserve enough space in the stack and copy character by character from the constant part of the memory. Unfortunately, you don't have access to the constant part that stores the string literal because you are telling the program that you want the values to be modifiable (string stored in stack), so it gives what you asked.

CMPS
  • 7,733
  • 4
  • 28
  • 53
0

When this statement is compiled

char str[] = "Hello world!";

the compiler does not keep the string literal in the program. it is used only to initialize the array.

If you want to keep the string literal then you have to write the following way

char *s = "Hello world!";
char str[13];

strcpy( str, s );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Most of your question has been addressed in the other answers, However, I did not see anyone address this one specifically:

Regarding your question: ...can I read or point to the original string after modifying the copy I'm given, and how?

The following sequence demonstrates how you can read the original after modifying a copy:

char str[] = "hello world"; //creates original (stack memory)

char *str2 = 0;//create a pointer  (pointer created, no memory allocated)

str2 = StrDup(str); populate pointer with original (memory allocated on heap)

str2[5]=0;  //edit copy:  results in "hello" (i.e. modified)  (modifying a location on the heap)

str; //still contains "hello world"  (viewing value on the stack)

EDIT (answering comment question)

The answer above only addressed the specific question about accessing an original string after a copy has been modified. I just showed one possible set of steps to address that. You can edit the original string too:

char str[] = "Hello world!"; //creates location in stack memory called "str",
//and assigns space enough for literal string: //"Hello world!", 13 spaces in all (including the \0)
strcpy(str, "new string"); //replaces original contents with "new string" //old contents are no longer available.

So, using these steps, the original values in the variable str are changed, and are no longer available.
The method I outline in my original answer, (at top) shows a way whereby you can make an editable copy, while maintaining the original variable.

In your comment question, you are referring to things such as system memory and constant memory. Normally, system memory refers to RAM implementations on a system (i.e. how much physical memory). By constant memory, my guess is that you are referring to memory used by variables created on the stack. (read on)

First In a development, or run-time environment, there is stack memory. This is usually defaulted to some maximum value, such as 250,000 bytes perhaps. It is a pre-build settable value in most development environments, and is available for use by any variable you create on the stack. Example:

int x[10];   //creates a variable on the stack 
             //using enough memory space for 10 integers.  

int y = 1;   //same here, except uses memory for only 1 integer value  

Second There is also what is referred to a heap memory. The amount of heap memory is system dependent, the more physical memory your system has available, the more heap memory you can use for variable memory space in your application. Heap memory is used when you dynamically allocate memory, for example using malloc(), calloc(), realloc().

int *x=0;        //creates a pointer, no memory allocation yet...
x = malloc(10);  //allocates enough memory for 10 integers, but the 
                 //memory allocated is from the _heap_  
                 //and must be freed for use by the system
                 //when you are done with it.
free(x);

I have marked the original post (above) with indications showing what type of memory each variable is using. I hope this helps.

ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Doesn't that just duplicate the string though? Perhaps the issue is I don't understand enough about system memory to be asking this question but if I declare "int x = 1;" is the value 1 stored in constant memory, then copied to the variable x? If not, I really don't understand why it has to be that way with a string – Techmaster21 Jul 01 '14 at 19:28
  • @Techmaster21 - It matters where, and how you create a variable, and in some instances how you provide memory. See my edit for details – ryyker Jul 01 '14 at 19:57