Initialization vs Assignment in C
My instructor recently told that array initialization in C happens in two ways, namely:
- Manually like
int a[5]={1,2,3,4,5};
- Using
scanf()
likeint a[5], i; for(i=0;i<5;i++) scanf("%d", &a[i]);
In my opinion the second "way" is a way of assignment and not initialization. So I decided to check what people over here have to say about this. I stumbled upon this post where one answer claims:
If all you are asking about is terminology (*which isn't really clear from your question), "Initialization" of a variable is, literally, the first time a value is assigned to it. This term comes from the fact that you are giving the variable it's "initial" value.
This should (obviously) happen before it is used the first time.
int x=5;
is a declaration and an initialization, and is really just convenient shorthand for
int x; x=5;
If I'm to follow what this particular answer claims, then the second way of "initialization" is correct, because no value was assigned prior to the scanf()
statement. However, thanks to my knowledge on static variables a new doubt arises in my mind. Consider the following code:
#include <stdio.h>
void first_way(){
static int x[2]={1,2};
printf("first_way called %d time(s)\n",++x[0]);
}
void second_way(){
int i;
static int x[2];
for(i=0;i<2;i++)scanf("%d",&x[i]);
printf("second_way called %d time(s)\n",++x[0]);
}
int main(void){
int i;
for(i=0;i<3;i++)
first_way();
printf("\n#######\n");
for(i=0;i<3;i++)
second_way();
return 0;
}
Its output is like this:
first_way called 2 time(s)
first_way called 3 time(s)
first_way called 4 time(s)
#######
1 2
second_way called 2 time(s)
1 2
second_way called 2 time(s)
1 2
second_way called 2 time(s)
This output again leads me to think of scanf()
version more like an assignment version rather than initialization even though no value to elements of x[]
were assigned before the scanf()
statement. Back to square one.
So, is the second version really an initialization like my instructor claims or merely an assignment (which is what I believe)?
Edit:
After someone pointed out, I feel my static
array example is a poor one as static
variables are implicitly initialized to 0 no matter what. Then again, someone else pointed me towards const
variables.
Consider const int x = 2;
Here one can initialize x
, but cannot assign any value to it after initialization. But this is conflicting with the answer that claims (I quote it again):
int x = 5;
is a declaration and an initialization, and is really just convenient shorthand forint x; x=5;
So, after all this, does the scanf()
version qualify as an initializer?
Solution 1:
In the C Standard, only option (1) is initialization.
In programming jargon, both may be considered initialization. Your question is really asking about the meanings of words.
It's normal for people to use words with various common meanings, instead of switching terminology for particular languages. Another example is "pass by reference". Does C have pass by reference or not? Some would argue it only has pass by value, others would argue that passing by pointer implements the concept of "pass by reference".
Then we could talk about deep copy vs shallow copy (which is not mentioned by the C Standard at all), or the terms "stack" and "heap" (which are not mentioned by the C Standard either, but commonly used by C programmers), and so on.
If you say { int b; b = 5; }
isn't initialization (because the C Standard says it isn't) then, to be consistent, you should also say that b
is not a stack variable.
Solution 2:
There are two very closely related concepts in play here.
An initializer is a specific syntactic construct. In the declaration
int n = 42;
the 42
is an initializer. In the statement
n = 42;
the 42
is not an initializer
; n = 42
is syntactically an assignment-expression.
On the other hand, the standard also uses the word "initialized" to refer to things other than initializers. For example, quoting N1570 section 6.3.2.1:
If the lvalue designates an object of automatic storage duration that could have been declared with the
register
storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
So an initializer is always part of a declaration, not an assignment -- but an object is said to be initialized either if it was defined with an initializer, if it was implicitly initialized because it's static, or if a value has been assigned to it.
Solution 3:
1) Declaration
int a;
2) Initialization
int a=10;
3) Assignmen
a=10;
Arrays can be initialized, but not assigned to.
int arrA[3] = {1,3,2};
This will be illegal:
arrB = arrA;
Solution 4:
According to N1570 6.7.9.1:
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designationopt initializer
initializer-list , designationopt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
So obviously, the second way isn't actually an "initialisation". However, it is functionally identical to an initialisation in most cases. What's more, you won't want to use an initialiser-list when specifying the initial value stored in an array containing 10000 elements.