Open In App

Storage for Strings in C

Last Updated : 30 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report
 

In C, a string can be referred to either using a character pointer or as a character array. 

Strings as character arrays  

C




char str[4] = "GfG"; /*One extra for string terminator*/
/*    OR    */
char str[4] = {‘G’, ‘f’, ‘G’, '\0'}; /* '\0' is string terminator */


When strings are declared as character arrays, they are stored like other types of arrays in C. For example, if str[] is an auto variable then the string is stored in stack segment, if it’s a global or static variable then stored in data segment, etc.

Strings using character pointers 
Using character pointer strings can be stored in two ways:

1) Read only string in a shared segment. 

When a string value is directly assigned to a pointer, in most of the compilers, it’s stored in a read-only block (generally in data segment) that is shared among functions. 

C




char *str  =  "GfG"


In the above line “GfG” is stored in a shared read-only location, but pointer str is stored in read-write memory. You can change str to point something else but cannot change value at present str. So this kind of string should only be used when we don’t want to modify the string at a later stage in the program.

2) Dynamically allocated in heap segment. 

Strings are stored like other dynamically allocated things in C and can be shared among functions. 

C




char *str;
int size = 4; /*one extra for ‘\0’*/
str = (char *)malloc(sizeof(char)*size);
*(str+0) = 'G';
*(str+1) = 'f'
*(str+2) = 'G'
*(str+3) = '\0'


Let us see some examples to better understand the above ways to store strings.

Example 1 (Try to modify string) 

The below program may crash (gives segmentation fault error) because the line *(str+1) = ‘n’ tries to write a read only memory. 

C




int main()
{
 char *str;
 str = "GfG";     /* Stored in read only part of data segment */
 *(str+1) = 'n'; /* Problem:  trying to modify read only memory */
 getchar();
 return 0;
}


The below program works perfectly fine as str[] is stored in writable stack segment. 

C




int main()
{
 char str[] = "GfG"/* Stored in stack segment like other auto variables */
 *(str+1) = 'n';   /* No problem: String is now GnG */
 getchar();
 return 0;
}


Below program also works perfectly fine as data at str is stored in writable heap segment. 

C




int main()
{
  int size = 4;
 
  /* Stored in heap segment like other dynamically allocated things */
  char *str = (char *)malloc(sizeof(char)*size);
  *(str+0) = 'G';
  *(str+1) = 'f'
  *(str+2) = 'G';   
  *(str+3) = '\0'
  *(str+1) = 'n'/* No problem: String is now GnG */
   getchar();
   return 0;
}    


Example 2 (Try to return string from a function) 
The below program works perfectly fine as the string is stored in a shared segment and data stored remains there even after return of getString() 

C




char *getString()
{
  char *str = "GfG"; /* Stored in read only part of shared segment */
 
  /* No problem: remains at address str after getString() returns*/
  return str; 
}    
 
int main()
{
  printf("%s", getString()); 
  getchar();
  return 0;
}


Output

GfG

The below program also works perfectly fine as the string is stored in heap segment and data stored in heap segment persists even after the return of getString()  

C




char *getString()
{
  int size = 4;
  char *str = (char *)malloc(sizeof(char)*size); /*Stored in heap segment*/
  *(str+0) = 'G';
  *(str+1) = 'f'
  *(str+2) = 'G';
  *(str+3) = '\0'
   
  /* No problem: string remains at str after getString() returns */   
  return str; 
}    
int main()
{
  printf("%s", getString()); 
  getchar();
  return 0;
}


Output

GfG

But, the below program may print some garbage data as string is stored in stack frame of function getString() and data may not be there after getString() returns. 

C




char *getString()
{
  char str[] = "GfG"; /* Stored in stack segment */
 
  /* Problem: string may not be present after getString() returns */
  /* Problem can be solved if write static before char, i.e. static char str[] = "GfG";*/
  return str;
}    
int main()
{
  printf("%s", getString()); 
  getchar();
  return 0;
}


Output

???B?

You know that String s= “Aakash”;
It is causing heap allocation and it is very costly and you have to go through each and every step and then return.
->A
->a
->k
->a
->s
->h
As you can see so many allocations involved that made heap costly. To make it efficient, memory for large string is allocated on heap whereas for small string it is allocated on static buffer. E.g., If string is more than 25 characters as in the case of MAC then it will go only to Heap and get the memory, otherwise it would be going to static buffer available in string classes, it maybe varies according to compiler and systems. In some cases it maybe less than 25 or in some cases it maybe more. 
 

Suppose you have “CppNuts”-> a string that you seriously want to allocated on heap and to do that you need to override new operator which will always allocate memory on heap.
 

Example:

C++




#include <iostream>
using namespace std;
 
// Overloading Operator
void* operator new(size_t s)
{
    cout << "Allocated Heap!!" << endl;
    return malloc(s);
}
 
int main()
{
    std::string str1 = "Hello this is Aakash Here!!";
    // 27 char it is greater than 25
   
    std::string str2 = "CppNuts";
    // 7 char it is smaller than 25
}


Output

Allocated Heap!!
Allocated Heap!!

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads