The rule is that variables should be set before they're used.
You do not have to explicitly initialize them on creation if you know you will be setting them elsewhere before use.
For example, the following code is perfectly okay:
int main (void) {
int a[1000];
: :
for (int i =0; i < sizeof(a)/sizeof(*a); i++)
a[i] = i;
: :
// Now use a[whatever] here.
: :
return 0;
}
In that case, it's wasteful to initialize the array at the point of its creation.
As to whether there's a performance penalty, it depends partially on where your variable is defined and partially on the execution environment.
The C standard guarantees that variables defined with static storage duration (either at file level or as statics in a function) are first initialized to a bit pattern of all zeros, then set to their respective initialized values.
It does not mandate how that second step is done. A typical way is to just have the compiler itself create the initialized variable and place it in the executable so that it's initialized by virtue of the fact that the executable is loaded. This will have no performance impact (for initialization, obviously it will have some impact for program load).
Of course, an implementation may wish to save space in the executable and initialize those variables with code (before main is called). This will have a performance impact but it's likely to be minuscule.
As to those variables with automatic storage duration (local variables and such), they're never implicitly initialized unless you assign something to them, so there will also be a performance penalty for that. By "never implicitly initialized", I mean the code segment:
void x(void) {
int x[1000];
...
}
will result in x[] having indeterminate values. But since:
void x(void) {
int x[1000] = {0};
}
may simply result in a 1000-integer memcpy-type operation (more likely memset for that case), this will likely to be fast as well. You just need to keep in mind that the initialization will happen every time that function is called.