Reputation: 1181
Consider below example
void func(int i){
if(i) {
int arr[2048] = {0};
//Doing something related to arr;
} else {
//Doing something
}
}
I have a large array declaration in the if
block. The initialization of this array should cost some time. My question is: if i == 0
, will this array be initialized at all?
Upvotes: 2
Views: 2530
Reputation: 213276
In practice, a variable will be initialized before use, regardless if it is placed in an inner scope or not. This code:
void func1 (int i){
if(i) {
int arr[2048] = {0};
printf("%d", arr[666]);
} else {
//Doing something
}
}
gives exactly the same machine code as this code:
void func2 (int i){
int arr[2048] = {0};
if(i) {
printf("%d", arr[666]);
} else {
//Doing something
}
}
gcc -O3 on x86 gives:
.LC0:
.string "%d"
func1:
test edi, edi
jne .L4
ret
.L4:
xor esi, esi
mov edi, OFFSET FLAT:.LC0
xor eax, eax
jmp printf
and
.LC0:
.string "%d"
func2:
test edi, edi
jne .L7
ret
.L7:
xor esi, esi
mov edi, OFFSET FLAT:.LC0
xor eax, eax
jmp printf
As you can see they are identical.
It is good design practice to limit the scope of variables as much as possible though, but that has nothing to do with performance.
Upvotes: 1
Reputation: 4877
To understand the compiler behavior you should consider that in the C language each variable has a storage class (ISO/IEC 9899:201x §6.2.4 Storage durations of objects) which characterize it behavior and its 'life', that means the existence of such an object (a variable is an object), and the legal access conditions to it. The storage classes are 4: static, thread, automatic, and allocated. The latter use dynamic memory allocation.
In your case the array arr[2048]
is an automatic object, which lifetime is defined (in the same paragraph of the standard @ point 6) as:
For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. (Entering an enclosed block or calling a function suspends, but does not end, execution of the current block.)
If the block is entered recursively, a new instance of the object is created each time.
The initial value of the object is indeterminate.
If an initialization is specified for the object, it is performed each time the declaration or compound literal is reached in the execution of the block; otherwise, the value becomes indeterminate each time the declaration is reached.
This explain that:
The first point is clear, and is already the answer to your question. The code you reference is:
{ //Block init
int arr[2048] = {0};
//Doing something related to arr;
} // block end
If you don't enter the block the life of your object, the array, doesn't begin: the array doesn't exist. Of course under this condition no operations can be performed on the object, even initialization.
Now the point 2 helps to clarify better. The expression:
int arr[2048] = {0};
Isn't functionally interpreted by the compiler as a declaration with object initialization, because of the storage class of the array object. It is, substantially, treated moreover as a declaration plus an assignment.
What's the difference?
A declaration of an initialized variable having storage class different from automatic is implemented with a mechanism transparent to the user code, statically assigning values in the BSS section or with code belonging to the compiler prologues and epilogues, that could happen even if the object is not accessed.
In the other case the initialization code, the assignment, is part of the user code, and for this reason executed following the execution flow logic.
This is the official behavior. Inspecting under the hood you can see that in some cases the space for automatic variables happen to be allocated in advance from the object life beginning, but these behavior are strictly depending on the CPU architecture, and basically when happen don't create functional divergence between the code the language standard (which is the basic property of a compliant compiler).
Upvotes: 3
Reputation: 32586
if i == 0, will this array be initialized at all?
because your code is
if(i) { int arr[2048] = {0}; //Doing something related to arr; } else { //Doing something }
the array does not exist if i==0
so it cannot be initialized, the array only exists in the branch of the if where i != 0
Upvotes: 6