2

What is the difference between const char* and static const char* in C?

I think that the answer of Difference between static const char* and const char* is wrong.

Indeed, const char* elements are put in the .rodata section of the program, otherwise the following would lead to a segfault:

const char* f() {
    const char* hello = "hello";
    return hello;
}

int main() {
    const char* hello_after = f();
    printf("%s\n", hello_after);
}

Indeed, because that code works, the pointer returned by f is still pointing to alive data, which shows that that data is not allocated on the stack but stored in .rodata.

But then, it seems to me that const char* and static const char* are the same things as far GCC is concerned.

But then, why the behavior not the same for const int* and static const int*? Is that an exception, hardcoded in GCC, that only for the type char then const and static const should be the same?

Thank you very much for your help!

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Cosmo Sterin
  • 171
  • 8
  • 1
    This is less related to `const char*` and more to string literals (`"hello"` in this case) – UnholySheep Apr 19 '20 at 14:25
  • 2
    I think you misunderstand the linked answer. They discuss where the pointer is stored - not the string literal. The pointers will be stored differently depending on the use of `static` – Support Ukraine Apr 19 '20 at 14:26
  • also if you compile with `-fsanitize=address` you get an runtime error (https://godbolt.org/z/37rH-L) – nicksheen Apr 19 '20 at 14:27
  • 1
    Quote: "Indeed, const char* elements are put in the .rodata section of the program..." Wrong - the string literal is but not the pointer . – Support Ukraine Apr 19 '20 at 14:36

1 Answers1

4

In this function declaration

const char* f() {
    const char* hello = "hello";
    return hello;
}

the pointer hello points to the string literal "hello" that has the static storage duration. That is it is not the pointer that has the static storage duration it is the pointed literal that has the static storage duration. In each call of the function the pointer is initialized anew.

If you will declare the function like

const char* f( ) {
    static const char* hello = "hello";
    return hello;
}

then in this case the pointer itself has the static storage duration. It is initialized once before the program gets the control and its value is kept between function calls.

For example consider this demonstrative program.

#include <stdio.h>

const char* f( int i ) 
{
    static const char* hello = "hello";

    if ( i == 1 ) hello = "bye";
    else if ( i == -1 ) hello = "hello";

    return hello;
}

int main(void) 
{
    puts( f( 0 ) );
    puts( f( 1 ) );
    puts( f( 0 ) );

    return 0;
}

Its output is

hello
bye
bye

That is initially the pointer hello was initialized by the string literal "hello".

Then due to this call

    puts( f( 1 ) );

its value was changed. Now it points to the string literal "bye".

And for the third call

    puts( f( 0 ) );

the pointer keeps the value that was assigned to it by the previous call of the function.

It is due to the fact that the pointer has the static storage duration.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thank you, I understand your answer! So I guess that what is unique here is the fact the we are dealing with string literals? If instead, we had `const int hello[5] = {1,2,3,4,5};` , the "array literal", {1,2,3,4,5} is not stored in `.rodata` by GCC? – Cosmo Sterin Apr 19 '20 at 14:45
  • @CosmoSterin In that example you have an array object, not a pointer object, which changes things some. An implementation can do anything under the covers that gives the correct result, but note that if the function is entered recursively, there must be two `hello` arrays with different addresses. – aschepler Apr 19 '20 at 14:54
  • Ok! I didn't now that C was treating arrays differently than pointers. – Cosmo Sterin Apr 19 '20 at 14:57
  • @CosmoSterin This {1,2,3,4,5} is not an "array literal". this is initializers that used to initialize elements of an array. It is the same as you will wrote in a block scope char s[] = "hello"; The characters of the string literal used to initialize the array. But the array itself does not have the static storage duration if it is declared without the storage specifier static. – Vlad from Moscow Apr 19 '20 at 15:16