Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is declaring a string literal with a pointer more memory efficient than declaring constant array?

Tags:

c

pointers

If I want to store a constant string,

const char array[] = "Some string literal.";

The C primer plus book says

then the quoted string is stored in a data segment that is part of the executable file. Memory for the array is allocated only after the program begins running. At that time, the quoted string is copied into the array.

Does this mean memory is allocated twice for the string literal?

On the other hand when declared with pointer, it only sets aside the storage for the pointer variable and stores the address of string literal into it.

const char *pt = "Some string literal.";

Which means there is only one copy of the string literal and declaring pointer with string literal is more memory efficient than array?

like image 880
R__raki__ Avatar asked Jan 29 '17 10:01

R__raki__


People also ask

Why we use pointer in string?

Because ptr points to the location of the first character of the string, when you do *ptr you are accessing the contents of the first char of that string. So it expects a char, not a string. So it would be something like: *ptr = 'a' ; 2- Well, that's the way printf works.

Are string literals arrays?

String literals are stored in C as an array of chars, terminted by a null byte.

Can you write memory to a literal?

All memory is flat and writable. Hence, writing to the literal was well defined (as it was in any sort of const variable) at the time.

Is it possible to modify string literal in C?

Attempting to modify the string literal has undefined behavior. However, modifying a mutable array of char directly, or through a pointer is naturally not undefined behavior, even if its initializer is a literal string.


2 Answers

In the first case the data for the string is stored in the executable file, and it's stored in memory once the program is loaded. So yes it is "allocated twice" but in very different storage mediums (disk and memory).

However, the same is true for the second case as well. The string literal needs to be stored once in the executable file on disk, and once in memory when the program is running.

The difference is an implementation detail, namely that in the first case the string in memory is stored either on the stack or in some global modifiable data memory segment. In the second case the string is usually stored together with the code.

So if you only have one instance of the string in the first case, there is no difference in "memory efficiency".

like image 181
Some programmer dude Avatar answered Oct 10 '22 09:10

Some programmer dude


The answer depends on whether the definition appears at global or local scope.

  • At global scope:

    • The first option defines an initialized constant array. Reading bytes from it with array[0] will result in code that reads single bytes from a global memory location, usually a single instruction.

    • The second option defines a modifiable pointer initialized to point to a constant array of characters. Reading bytes from it with array[0] will result in code that loads the pointer value and reads the element pointed by the pointer, usually at least 2 instructions.

    If you do not need to change the string array refers to, it would probably be preferable to use the first option.

  • At local scope (automatic storage)

    • The first option defines an array initialized with a string. If this array was not constant and was modified inside the function, the code generated would be substantially similar to this:

      char array[sizeof "Some string literal."];
      memcpy(array, "Some string literal.", sizeof(array));
      

      But since it is defined as const, the compile could optimize the code and generate references to array as references to the string literal in static storage. To avoid potential code generation such as the above, you could use this definition at local scope:

      static const char array[] = "Some string literal.";
      
    • Conversely, the second option defines a local pointer initialized to point to a string literal, itself most likely stored in static storage such as a data segment or even the code segment. Provided the function uses array, the definition could generate a store to initalize the pointer and more or less code to read characters from it depending on the specific code inside the function and how efficient the compiler is.

At global scope it seems more efficient to use the first approach.

At local scope, it depends a lot on the actual code and compiler used, but defining a static const char array might be the most efficient.

like image 36
chqrlie Avatar answered Oct 10 '22 11:10

chqrlie