1

I read that while using character pointer declaration first the string literal is getting stored in static storage and then pointer to it is returned. but is same happening while using literals in char array?

here I know "instatic" gets stored in static storage because it is char literals and then test receives the address of the first character.

char *test = "instatic";

but in this declaration it also uses char literals and are they first located in static storage and then they get copied to stack?

char test[] = "instatic?";

Aka
  • 33
  • 5
  • 1
    The second form doesn't really create a string literal. It just initializes your character array. – Tom Karzes Jul 27 '23 at 13:25
  • 1
    @TomKarzes There *might* be a string literal stored, but it's an implementation detail. – dbush Jul 27 '23 at 13:28
  • It's moderately likely that the `"instatic?"` string is stored somewhere; that 'somewhere' won't be directly accessible to the programmer, and won't be modifiable. The value would be copied into the storage allocated for the array; the data in the array is modifiable, of course. – Jonathan Leffler Jul 27 '23 at 13:33
  • @TomKarzes: A string literal used to initialize an array is still a string literal. – Eric Postpischil Jul 27 '23 at 13:38
  • 1
    @EricPostpischil I didn't word it well. What I meant is that no storage is used for the string literal in the object file. I.e., it doesn't allocate memory for the string literal in the object file. That's what I meant by "create". That assumes the array is static. I would expect the string to be stored as initial data for the array, but not elsewhere. – Tom Karzes Jul 27 '23 at 14:04

2 Answers2

4

Formally, a string literal is text in source code that is a sequence of characters enclosed in " marks, optionally with an encoding prefix of u8, u, U, or L, per C 2018 6.4.5 1.

In the abstract model of computing used in the C standard, any string literal, regardless of how it is used, results in the creation of an array of static storage duration that is initialized with the contents of the string, including a terminating null character, per 6.4.5 6.

That static array might or might not appear in the actual program generated by a compiler, depending on how it is used and how the compiler optimizes the program. In other words, the abstract program described by the C standard always contains a static array for a string literal, but the actual program produced by a C compiler, with optimization, might produce the same behavior as the abstract program without actually using a separate static array for the string literal, per 5.1.2.3 6.

In the case of char *test = "instatic";, the compiler generally must create the static array so that test can point to it. (This might not occur if test is not used or perhaps if only individual characters from the array are used, as the compiler could then perform some optimizations that make the full array unnecessary.)

In the case of char test[] = "instatic?"; appearing at file scope, a compiler typically produces object code that defines the array test with the contents of the string, so a separate static array for the string is not needed. This is a form of optimization: In the abstract model of computing, an array for the string is created, separate memory is allocated for test, and the contents of the string are copied into the array. However, in practice, the contents of the string are made to be the initial contents of memory for the array as part of the program loading process.

In the case of char test[] = "instatic?"; appearing at block scope (inside a function), the compiler generally needs to create that separate static array for the string, because, each time execution of the block begins, the compiler has to allocate memory for the test array and then initialize it. This cannot be made part of the program loading process because it has to happen multiple times during program execution. Again, optimization may be able to reduce this, depending on circumstances.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • so in the case of ```char test[] = "instatic?";``` in block scope compiler creates static array for string literal "instatic?" and every time variable test gets created it needs to copy previously made characters in static storage into new array in stack right? – Aka Jul 27 '23 at 14:12
  • 1
    @AkakiUjarashvili: Yes, generally, unless there is some optimization available. For example, if the compiler can see the array is not used, then it does not need to provide memory for it or create the string literal. Or if it can see only one character is used from the array, it can provide just that character. Or if it can see the function is called only once (perhaps because it is declared `static` and called once from `main`), the compiler can treat the array like a static array. But, in the general case, the compiler has to create a separate array for the string literal and copy it. – Eric Postpischil Jul 27 '23 at 14:15
  • It would be more accurate to use storage duration as the distinguishing feature rather than scope. – Ian Abbott Jul 27 '23 at 14:31
4

I read that while using character pointer declaration first the string literal is getting stored in static storage and then pointer to it is returned.

That's a somewhat confusing way to describe it, as if there were some kind of special case behavior. In fact, that behavior falls out naturally from other, more basic aspects of the language specification:

  1. A string literal represents an array of char with static storage duration.

  2. Expressions of array type, such as string literals, decay to pointers under most circumstances. Specifically:

    Except when it is the operand of the sizeof operator, or typeof operators, or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.

    (C23 6.3.2.1/3)

Thus, when you have a string literal as the initializer for anything other than an array, it is automatically converted to a pointer. In your particular case, that pointer is suitable for initializing pointer variable test, so all is good.

but is same happening while using literals in char array?

No. As the excerpt above says, a string literal used as the initializer for an array in fact is a special case. The array decay that usually applies does not occur here. Instead, this case is covered with its own initialization rule:

An array of character type may be initialized by a character string literal or UTF-8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

(C23 6.7.10/15)

and are they first located in static storage and then they get copied to stack?

If the variable being initialized has static storage duration (on account of being declared at file scope or with the static storage-class specifier) then probably not. Semantically, such variables have their initial values already when execution of the program begins. And, such variables generally do not live on the stack.

But if the variable being initialized has automatic storage duration -- that is, it is an ordinary local variable -- then (more or less) each entry into its scope produces a new object, which must be initialized. The initial value needs to be stored somewhere else, and indeed copied in every time. The source from which it is initialized is not directly visible to the program, however, and in practice, it might or might not be analogous to the storage for the string-literal initializer in the pointer case.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157