All external data objects, i.e. those declared outside of a function, and all local variables declared to be in the static storage class, are, by default, initialized to zero before the program starts. If it is a compound data type, then all parts are zeroed. Local, or automatic data objects are, by default not initialized - they have random values which will depend on what programs have executed prior to your program, and perhaps what sequence of functions calls have already taken place in you program.
It is possible to explicitly initialize all external variables and all local static variables of any type. To explicitly initialize these static variables to other than 0, follow the identifier in the declaration with an equal sign, =, followed by a constant expression where the conversion rules of assignment apply. Here are some examples:
int x=-6; float y=2; /* compiler automatically converts */ char z='z'; /* i.e. "z" has the ASCII code for 'z' */
Aggregate local variables, i.e. arrays, structures and unions, cannot be initialized. If a local variable, i.e. of auto or register storage class, is explicitly initialized, then its value is set each time execution control enters the block in which it is declared. The initialization expression for a local variable does not have to be a compile time constant.
Note that the address of a local variable of automatic storage class is not a constant because it can change for each call to the function. The address of a register variable is not allowed at all. Having a pointer to a local variable which is used after that function has returned is not guaranteed to still point to that data object, because another function may have over-written it on the stack.
For the compound types there are two kinds of initializations. For Arrays of char, the array can be initialized by a string_literal, in which case each element of the array will receive the characters in the string_literal plus the terminating NUL (all bits 0) byte. Note that a variable of type pointer to char, if initialized with a string_literal, would be assigned the address of the string_literal. The string_literal itself would be placed somewhere in memory by the compiler.
Otherwise, all compound types can always be initialized by a comma separated list of values within curly braces. The values within the list are either simple or compound in which case they also are within curly braces. Thus for arrays, these braces nest according to the dimensionality of the array. A union, though, is initialized according to the type of the first field in its definition.
As an example of initialization for arrays:
int a[2][3] = { { 0,1,2 }, { 4,5,6 } };
An example for a structure is:
struct { int v; char name[20]; float temp[3]; } z = { 29, "Left rear engine block", { 212.0, 24.3, -57 } };
If more elements are given then needed then the compiler gives an error message. If too few are given, then the remainder are always 0.
If an array is being initialized, and the size of the array does not appear in the declaration, then the size will be determined by the size of the initialization list. If there is no initializer, then the compiler will give an error message about unknown size.
char msg[] = "This message is 31 bytes long\n"; int foo[] = { 12,13,5,7,-9 }; /* array of 5 elements */