Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scope of char * compared with char array in C

Tags:

c

scope

These two forms of the same variable, when defined within scope of a function block should, I would think, have identical scope, i.e. within the function blocks {...} where they are defined:

char str1[] = "int_1 < int_2";

char *str1 = "int_1 < int_2";  

But my observation is that the char * lives beyond function scope, while the char [] ceases to exist. The symbol name str1 in both cases points to the location in memory where the variable is created, so why does one seem to live beyond the function, while the other does not? The following code can be used to test this behavior: (Changing #define from 0 to 1 selects one form over the other for illustration.)

Note also that that although the static modifier could be used to modify scope, it is purposely not used here to observe behavior without it.

#define DO (1)  //define as either 1 or 0

char * compare_int(int x1, int x2);

int main(void)
{
    int a = 0;
    int b = 0;
    int c = '\n';

    srand(clock()/CLOCKS_PER_SEC);

    while(c != 'q')
    {
        a = rand()%3;
        b = rand()%3;
        printf("%s\n( enter 'q' to exit. )\n\n", compare_int(a, b));
        c = getchar();
    }
    return 0;
}

char * compare_int(int x, int y) 
{
    printf("%d    %d\n", x, y);

#if(DO)
    char str1[] = "int_1 < int_2";
    char str2[] = "int_1 == int_2";    
    char str3[] = "int_1 > int_2";
#else
    char *str1 = "int_1 < int_2";
    char *str2 = "int_1 == int_2";    
    char *str3 = "int_1 > int_2";
#endif  

    return x < y ? (str1) : x == y ? (str2) : (str3);

}

I have read this, and it does answer some key parts to this question, but comments on any UB in my code, and/or references to C99 or newer standard pointing to paragraph(s) that make the distinctions between these two forms would also be appreciated.

like image 621
ryyker Avatar asked Jun 17 '20 15:06

ryyker


People also ask

What is the difference between char * and char array?

The main difference between them is that the first is an array and the other one is a pointer. The array owns its contents, which happen to be a copy of "Test" , while the pointer simply refers to the contents of the string (which in this case is immutable). Why is char* str commonly used when str denotes a string.

What is the difference between char array and char pointer in C?

For the array, the total string is stored in the stack section, but for the pointer, the pointer variable is stored into stack section, and content is stored at code section. And the most important difference is that, we cannot edit the pointer type string.

What is a char * array in C?

In C, an array of type char is used to represent a character string, the end of which is marked by a byte set to 0 (also known as a NUL character)

Which is faster char array or string?

char arrays prove to be much faster when you are working with simple string manipulation requirements and when you know the maximum size of the string.


1 Answers

This:

char str1[] = "int_1 < int_2";

Defines an array initialized with the given string literal. If you return str1, because the array name decays to a pointer to its first element, you're returning a pointer to a local variable. That variable's lifetime end when the function returns, and attempting to subsequently use that address invokes undefined behavior.

This is documented in section 6.2.4p2 of the C standard:

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address, and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

In contrast, this:

char *str1 = "int_1 < int_2";  

Defines a pointer which is initialized with the address of a string literal. String constants have full program lifetime, so reading a pointer to one is safe. When you return str1 in this case, you're returning the value of str1 (not its address) which is the address of the string literal.

The lifetime of string literals is specified in section 6.4.5p6 of the C standard:

In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals. The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.

And static storage duration is defined in section 6.2.4p3:

An object whose identifier is declared without
the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

like image 174
dbush Avatar answered Oct 26 '22 23:10

dbush