152

I'm not sure what will be in the char array after initialization in the following ways.

1.char buf[10] = "";
2. char buf[10] = " ";
3. char buf[10] = "a";

For case 2, I think buf[0] should be ' ', buf[1] should be '\0', and from buf[2] to buf[9] will be random content. For case 3, I think buf[0] should be 'a', buf[1] should be '\0', and from buf[2] to buf[9] will be random content.

Is that correct?

And for the case 1, what will be in the buf? buf[0] == '\0' and from buf[1] to buf[9] will be random content?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
lkkeepmoving
  • 2,323
  • 5
  • 25
  • 31

6 Answers6

270
  1. The first declaration:

     char buf[10] = "";
    

    is equivalent to

     char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. The second declaration:

     char buf[10] = " ";
    

    is equivalent to

     char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. The third declaration:

     char buf[10] = "a";
    

    is equivalent to

     char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    

As you can see, no random content: if there are fewer initializers, the remaining of the array is initialized with 0. This the case even if the array is declared inside a function.

TYeung
  • 2,579
  • 2
  • 15
  • 30
ouah
  • 142,963
  • 15
  • 272
  • 331
  • 56
    For the sake of the person asking the question, it's worth pointing out that the C standard requires any partially-complete array initialisation to be padded with zero for the remaining elements (by the compiler). This goes for all data types, not just `char`. – paddy Sep 08 '13 at 21:54
  • 8
    @ouah why there is no '\0' at the end of buf[]? – lkkeepmoving Sep 08 '13 at 22:06
  • 22
    @lkkeepmoving `0` and `'\0` have the same value. – ouah Sep 08 '13 at 22:15
  • And why I can not do 'char buf[10]; buf = "a"' ? – lkkeepmoving Sep 08 '13 at 22:15
  • @lkkeepmoving because C requires you to initialize at declaration time. You then cannot assign a value to an array. – ouah Sep 08 '13 at 22:17
  • 1
    @lkkeepmoving Initialization and assignment are two different beasts, thus C lets you provide a string as an initializer for a char array, but forbids array assignments (as ouah said). – LorenzoDonati4Ukraine-OnStrike Sep 09 '13 at 03:24
  • @StevenPenny I rolled back your edit, it's correct but I don't think it adds anything more. – ouah Sep 29 '14 at 12:09
  • @ouah, What happens then when you have more elements than space? E.g. `char buff[3] = "abcdefghijkl";` ? Is this valid and identical to char `buff[3] = {'a', 'b', 'c'}`? – Pacerier Dec 19 '14 at 06:42
  • @Pacerier it is invalid as per c99, 6.7.8p1. – ouah Dec 19 '14 at 09:36
  • @ouah, Do you mean that `char buff[3] = "abcdefghijkl";` wouldn't compile? (I'm not a C coder.) Then why will [`char p3[5] = "String";`](http://stackoverflow.com/questions/8732325/how-to-declare-strings-in-c/8732358#comment-10874556) compile? – Pacerier Dec 19 '14 at 11:14
  • 3
    @Pacerier `char buff[3] = "abcdefghijkl";` is invalid. `char p3[5] = "String";` is also invalid. `char p[6] = "String";` is valid and is the same as `char p[6] = {'S', 't', 'r', 'i', 'n', 'g'};`. – ouah Dec 19 '14 at 11:17
  • @Pacerier for the terminology, there is a constraint violation in the two invalid examples, which means an compiler is required to issue a diagnostic and may refuse to compile the program. – ouah Dec 19 '14 at 11:20
  • what about char buf[] = {}? – Lei Yang Jun 23 '16 at 08:30
  • @LeiYang `char buf[] = {}` is invalid in C as empty initializers are not allowed. GNU C allows it and it declares an array of size `0`. – ouah Jun 23 '16 at 09:27
  • If you have a constant MAX = 5000, I will not put 0x500 in my code... is crazy solution!!!! if you want set a value in a function use "strcpy" please... –  Dec 01 '16 at 17:28
  • 2
    @delive What do you mean, and what relevance did it have to this answer? – underscore_d Oct 31 '17 at 09:24
  • 2
    `This is not how you initialize an array` what do you mean – Tiina Apr 25 '21 at 09:40
42
  1. These are equivalent

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. These are equivalent

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. These are equivalent

    char buf[10] = "a";
    char buf[10] = {'a'};
    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
Zombo
  • 1
  • 62
  • 391
  • 407
31

Edit: OP (or an editor) silently changed some of the single quotes in the original question to double quotes at some point after I provided this answer.

Your code will result in compiler errors. Your first code fragment:

char buf[10] ; buf = ''

is doubly illegal. First, in C, there is no such thing as an empty char. You can use double quotes to designate an empty string, as with:

char* buf = ""; 

That will give you a pointer to a NUL string, i.e., a single-character string with only the NUL character in it. But you cannot use single quotes with nothing inside them--that is undefined. If you need to designate the NUL character, you have to specify it:

char buf = '\0';

The backslash is necessary to disambiguate from character '0'.

char buf = 0;

accomplishes the same thing, but the former is a tad less ambiguous to read, I think.

Secondly, you cannot initialize arrays after they have been defined.

char buf[10];

declares and defines the array. The array identifier buf is now an address in memory, and you cannot change where buf points through assignment. So

buf =     // anything on RHS

is illegal. Your second and third code fragments are illegal for this reason.

To initialize an array, you have to do it at the time of definition:

char buf [10] = ' ';

will give you a 10-character array with the first char being the space '\040' and the rest being NUL, i.e., '\0'. When an array is declared and defined with an initializer, the array elements (if any) past the ones with specified initial values are automatically padded with 0. There will not be any "random content".

If you declare and define the array but don't initialize it, as in the following:

char buf [10];

you will have random content in all the elements.

verbose
  • 7,827
  • 1
  • 25
  • 40
  • "To initialize an array, you have to do it at the time of definition..." This, and the following line makes this better than the accepted answer. – Laurie Stearn Dec 28 '16 at 03:48
14

The relevant part of C11 standard draft n1570 6.7.9 initialization says:

14 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.

and

21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

Thus, the '\0' is appended, if there is enough space, and the remaining characters are initialized with the value that a static char c; would be initialized within a function.

Finally,

10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then:

[--]

  • if it has arithmetic type, it is initialized to (positive or unsigned) zero;

[--]

Thus, char being an arithmetic type the remainder of the array is also guaranteed to be initialized with zeroes.

3

Interestingly enough, it is possible to initialize arrays in any way at any time in the program, provided they are members of a struct or union.

Example program:

#include <stdio.h>

struct ccont
{
  char array[32];
};

struct icont
{
  int array[32];
};

int main()
{
  int  cnt;
  char carray[32] = { 'A', 66, 6*11+1 };    // 'A', 'B', 'C', '\0', '\0', ...
  int  iarray[32] = { 67, 42, 25 };

  struct ccont cc = { 0 };
  struct icont ic = { 0 };

  /*  these don't work
  carray = { [0]=1 };           // expected expression before '{' token
  carray = { [0 ... 31]=1 };    // (likewise)
  carray = (char[32]){ [0]=3 }; // incompatible types when assigning to type 'char[32]' from type 'char *'
  iarray = (int[32]){ 1 };      // (likewise, but s/char/int/g)
  */

  // but these perfectly work...
  cc = (struct ccont){ .array='a' };        // 'a', '\0', '\0', '\0', ...
  // the following is a gcc extension, 
  cc = (struct ccont){ .array={ [0 ... 2]='a' } };  // 'a', 'a', 'a', '\0', '\0', ...
  ic = (struct icont){ .array={ 42,67 } };      // 42, 67, 0, 0, 0, ...
  // index ranges can overlap, the latter override the former
  // (no compiler warning with -Wall -Wextra)
  ic = (struct icont){ .array={ [0 ... 1]=42, [1 ... 2]=67 } }; // 42, 67, 67, 0, 0, ...

  for (cnt=0; cnt<5; cnt++)
    printf("%2d %c %2d %c\n",iarray[cnt], carray[cnt],ic.array[cnt],cc.array[cnt]);

  return 0;
}
user3381726
  • 153
  • 1
  • 7
1

I'm not sure but I commonly initialize an array to "" in that case I don't need worry about the null end of the string.

main() {
    void something(char[]);
    char s[100] = "";

    something(s);
    printf("%s", s);
}

void something(char s[]) {
    // ... do something, pass the output to s
    // no need to add s[i] = '\0'; because all unused slot is already set to '\0'
}
  • You should not really make use of the *implicit int* rule. You should specify a type for `main()` (and you should also use `void`, i.e., `int main(void) { ... }`. C99 got rid of this rule, so this code will not compile for C99 and later. The other thing to note here is that *starting* with C99, if you omit `return` in main, there is an automatic `return 0;` placed/implied before the `}` at main's end. You are making use of implicit int rule which only works before C99, yet you are making use of the implicit `return` that only works with C99 and *later*; these two are obviously contradictory. – RastaJedi May 07 '16 at 10:12