Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is better way to initialize array of characters using string literal?

Tags:

arrays

c

I'm newbie in C language. I'm trying to understanding concept of array in C. I have a confusion about array initialize.

Which is better way to initialize array of characters using string literal?

char arr[3] = "xyz";

or

char arr[] = "xyz";

Thanks in advance.

like image 418
Ishvar Patel Avatar asked Feb 05 '17 05:02

Ishvar Patel


1 Answers

Unless under special circumstances, always prefer the second way, that is, by not typing the array's size explicitly. This avoids the bug you seemingly unnoticedly created in your example.

To understand this, you should first understand what exactly is a string. The null character is denoted by '\0'. A string is a series of zero or more non-null chars, terminated by a single null character. This last bit is very important. Look at the following code:

const char* my_string = "xyz";
size_t string_len = strlen( my_string ); // string_Len == 3

A pointer is just a memory address. It doesn't hold any type of size or length information in itself. Then, how can strlen() measure my_string's length? This is, of course, by measuring the amount of non-null characters from the string's beginning to just before the terminating null character. You might have now noticed that the terminating null character is implicit in a string literal. The above string literal creates an array in memory that looks like this:

 _______ _______ _______ _______
|       |       |       |       |
|  'x'  |  'y'  |  'z'  | '\0'  |
|_______|_______|_______|_______|
    ^
    |
`my_string` is a pointer to this cell

The array itself goes unnamed, but the compiler manages to give its first element's address as my_string's value. So, what happens with your first example?

char my_string[ 3 ] = "abc";

By the standard's definition a string literal has type char[ N ], where N is the string's length plus one to count for the null character (note that string literals are not declared const for historical reasons, but it is still undefined behavior to modify them). Thus, the above expression "abc" has the type char[ 4 ]. my_string, on the other hand, (which is now an array, not a pointer, BTW) has type char[ 3 ]. That is, you're setting a smaller array to a larger array, since 4 > 3. The standard mandates that, in this precise situation, where the null character of a string literal doesn't fit into the array, shall it be cut off. Thus, my_string looks like this in memory:

 _______ _______ _______
|       |       |       |
|  'a'  |  'b'  |  'c'  |
|_______|_______|_______|

Looks ok, but... wait. Where's the terminating null character? You chopped it off by explicitly declaring the array's size! Now, how is strlen() supposed to determine the string's length? It will just continue reading characters past the string until a null character is found by matter of coincidence. This is undefined behavior. On the other hand, by doing this:

const char[] my_string = "abc";

You won't be risking doing so. my_string's type will automatically be deduced to const char[ 4 ], and the null character will be preserved.

tl;dr Don't forget the terminating null character!

like image 188
3442 Avatar answered Oct 05 '22 01:10

3442