4

My instructor recently told that array initialization in C happens in two ways, namely:

  1. Manually like int a[5]={1,2,3,4,5};
  2. Using scanf() like int 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 for int x; x=5;

So, after all this, does the scanf() version qualify as an initializer?

Community
  • 1
  • 1
Mayank Verma
  • 633
  • 6
  • 19
  • I think I could argue `int x; x = 5` would be assignment because just saying `int x` initializes x to a garbage value. So yes, I think you're right. – DeepDeadpool Feb 26 '16 at 22:25
  • Well, what if something is initializable but not assignable? Try adding `const` like `const int a[5]={1,2,3,4,5};`? – user3528438 Feb 26 '16 at 22:31
  • 1
    According to the standard (C99 section 6.7.8.10), uninitialised objects with automatic storage duration (like local variables) have an *indeterminate value* (C99 section 3.17.2: "either an unspecified value or a trap representation"), but objects with static storage duration are *always initialised* to whatever a zero would be for that type. In other words, any `static int x[2];` is equivalent to `static int x[2] = {0, 0};` because it's `static`. –  Feb 26 '16 at 22:31
  • @Rhymoid Forgot about that one. Seems like `const` example is a better one. – Mayank Verma Feb 26 '16 at 22:35
  • @GheyPhistor: There is more to this. `int x;` at file level is a tentative _definition_, while an added initialiser makes it a "normal" definition. – too honest for this site Feb 26 '16 at 22:36
  • @MayankVerma `const` only describes access through the name, not the physical properties of the underlying object. –  Feb 26 '16 at 22:38
  • @alvits: No, there is no _initialisation_ in your example. These are all assignments. The first one however, can be called "initial assignment". An initialiser has different semantics, e.g. you can use an array or a struct without using a _compound literal_. – too honest for this site Feb 26 '16 at 22:39
  • @Rhymoid: `const` in C is jut a promise by the programmer not to change the object once initialised. It has not the same semantics like in C++. – too honest for this site Feb 26 '16 at 22:41
  • @Olaf: How is that different from what I wrote? –  Feb 26 '16 at 22:44
  • @MayankVerma: You are both wrong - he more than you, though. An initialiser is **always** part of a declaration (exactly: an _init-declarator_). The second reads values from input. They are no assignments in the strict sense. Note the variables might still be undeterminate after `scanf`. There has to be differentiated very carefull between initialisation as defined by the standard and the common language "first time setting to a defined value". An _initialiser_ has more implications. – too honest for this site Feb 26 '16 at 22:46
  • @Rhymoid: Your comment imply it is the compiler's job to check you don't change the `const` qualified object. This is not true. It is not even required to "warn" actually. – too honest for this site Feb 26 '16 at 22:47
  • @Olaf: That's exactly not what I wrote. –  Feb 26 '16 at 22:51
  • @Rhymoid: Which part of my last comment do you mean? They are mutually exclusive. – too honest for this site Feb 26 '16 at 22:53
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/104686/discussion-between-rhymoid-and-olaf). –  Feb 26 '16 at 22:56
  • @Olaf if you do this `const int a = 10` and latter `a = 3` is this not wrong, i mean because cannot assign to const ? – Michi Feb 26 '16 at 22:56
  • Probably a short Answer will be, `initialization` mean's to initiliaze a variable and `assignment` mean's assign value to a variable. – Michi Feb 26 '16 at 23:05
  • @Michi: Wrong prerequisite. It is not that you "cannot assign to `const`", but you _shall not_, because if you do, it invokes UB. That included the assignment might work very well. It is just that **you** break the contract. The compiler itself does not gurantee anything for a `const` qualifier. The fact that modern compiler actually **do** warn is just a(n much appreciated:) courtesy of their programmers, not a requirement of ther standard, as much as for a lot of other "problematic" code, e.g. assignment in a condition. – too honest for this site Feb 26 '16 at 23:12
  • @Olaf I like to stick with the Standard (C11) and with gcc-5.3 there is no just a warning. [Simply doesn't compile at all](http://pastebin.com/raw/MyWrNgxT) which I find it at a beginner level like me good. – Michi Feb 26 '16 at 23:17
  • It looks like after C99 and C11 reading from "uninitialized variable" results in "indeterminate value" rather than UB, hence it's correct to say variables are always initialized (initializable), either to a user-defined value or an "indeterminate value". I also have to agree the "can not" and "shall not" difference of modifying const qualified variable, similar to arguing on "you cannot/shall not break the law", because as a matter of fact, law is indeed breakable, so it's also correct to say const qualified variables are assignable. – user3528438 Feb 26 '16 at 23:22
  • @Michi: I don't care much if it warns or "errors" The standard does not even mention warning and error message during compilation actually. But it also does not require a _diagnostic message_ for potential UB. Actually it very seldom **requires** emitting such a message, but leaves that to the implementation. There is just anm informal list of "common warnings" in Annex I. – too honest for this site Feb 26 '16 at 23:23
  • @user3528438: Read on. IIRC, there is a statement that reading an indeterminate value actually **is** UB. Without splitting this, it would be impossible to have automatic variables without explicit initialiser which are nevertheless get a defined initial value later in the code. – too honest for this site Feb 26 '16 at 23:25
  • @user3528438 From my side as a beginner in `C`, in all books I read, that `initialization` was always present even if was with a garbage value too. Which means that `int a` is a `declaration` and an `initialization` with a garbage value. – Michi Feb 26 '16 at 23:25
  • @Michi: No! Initialisation implies setting a well-defined value! Of course, the memory cell allocated fopr the object **does** contain a bit-pattern. But the standard very well allows for special treatment, e.g. using a trap representation or allocate the actual RAM cells on the first write, etc. Some of these features are useful e.g. in high-security MCUs or maybe future CPUs. – too honest for this site Feb 26 '16 at 23:27
  • @Olaf Yes, me I just explain things which are present in books and not my personal opinion. I think, like I said to Daniel schwarz that `initialization is about creating object assignment is about setting some value to object` and this is the highest level of speaking for me, even if i know that you are not agree and I'm agree with you :) – Michi Feb 26 '16 at 23:30
  • @Michi: Please point me at where my statements contradict the standard or include "personal opinion"! As you have almost finished the standard, you should well be able to. – too honest for this site Feb 26 '16 at 23:34
  • @Olaf I can't :). Any way the OP should know that there is a difference between `const int a = 5;` and `a = 10` which means `assignment of read-only variable ‘a’` and `const int a = 5;` and `scanf("%d",&a);` which means `writing into constant object`. – Michi Feb 26 '16 at 23:38
  • @Olaf In C11 draft N1570(the only post C99 version I have access to now) I did not find anything saying reading from "indeterminate value" itself is UB, however reading "trap representation" is UB (6.2.6.1 ) and "indeterminate value" includes "trap representation"(3.19.2). However 6.2.1.6 footnote 50 says "an automatic variable can be **initialized** to a trap representation without causing undefined behavior". – user3528438 Feb 27 '16 at 00:02
  • @user3528438: It's too late here to show up the chain of proof to track down why it is UB. As that is also not part of the question, I'll leave it here. Maybe someone else takes over. – too honest for this site Feb 27 '16 at 00:05
  • 1
    @Olaf Anyway digging into N1570 for a few hours I've gained my share of knowledge. Thanks for being thorough. – user3528438 Feb 27 '16 at 00:07
  • 1
    **It was spelt out nowhere that the linked post speaks about a completely distinct programming language called C#**. – Antti Haapala -- Слава Україні Oct 09 '18 at 09:31

5 Answers5

7

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.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Can you please show the reference to C Standard so that I'm able to argue with my instructor over this? And, no. My question isn't really asking about the meaning. My question is about what the Standard says. If the Standard says `b` is not a stack variable, even I believe what the Standard says. – Mayank Verma Feb 27 '16 at 04:37
  • @MayankVerma read section 6.7.9, it defines what initialization is. sun qingyao's answer quotes the grammar – M.M Feb 27 '16 at 06:06
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.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
1

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; 
Michi
  • 5,175
  • 7
  • 33
  • 58
  • 1
    So, are you saying if we have `int a; a=10;`, `a` is never initialized? – David Schwartz Feb 26 '16 at 22:48
  • In your example, there is a declaration and latter an Assigment. `int a = 10` is an Initialization. – Michi Feb 26 '16 at 22:50
  • `int a;` at file-scope is not just a _declaration_, but a _tentative definition_. If that becomes a true definition, the variable is very well initialised. – too honest for this site Feb 26 '16 at 22:51
  • @olaf If you speak at that level, then David Schwarz has right too. – Michi Feb 26 '16 at 22:52
  • @Michi So that's a yes? It's perfectly fine to use a variable's value even if it has never been initialized then? – David Schwartz Feb 26 '16 at 22:54
  • Not necessarily. It depends if you have an automatic or static variable. I'm actually thinking the question is too broad; an comprehensive answer would require explaining quite a lot from the standard. – too honest for this site Feb 26 '16 at 22:56
  • @DavidSchwartz `initialization` is about creating object `assignment` is about setting some value to object – Michi Feb 26 '16 at 22:57
  • @DavidSchwartz: Reading an uninitialised variable is always a "bad idea". The question is when is it automatically initialised. – too honest for this site Feb 26 '16 at 22:58
  • @Michi That conflicts with your answer which says `int a;` is declaration and not initialization. It crates an object. (Olaf: According to his answer, it's perfectly fine. `int a; a = 10;` has no initialization, but it's perfectly fine to read it.) – David Schwartz Feb 26 '16 at 22:58
  • @Michi: Not really. _definition_ is about creating an object, i.e. allocating space for it, etc. _Initialisation_ is about setting an initial value. Point is, in C they are grammatically combined; i.e. the semantics of a declaration may change if you add an _initialiser_ - depending on other context. – too honest for this site Feb 26 '16 at 23:00
  • @DavidSchwartz same as for Olaf, its only about of which level of speaking we are try to speak here. Me i'm a `C` beginner. Please leave an Answer if you feel that is a better one needed. – Michi Feb 26 '16 at 23:00
  • I don't think that my Answer is wrong, its only a beginner level Answer which makes it OK, i hope. – Michi Feb 26 '16 at 23:02
  • @DavidSchwartz: It certainly is ok, iff(!) you have the **initial assignment** before any read access. Whether `a` is initialised _before_ the assignment depends on if it is a static (not to confuse with the specifier!) or an automatic variable. – too honest for this site Feb 26 '16 at 23:03
  • @Michi: I fully understand and talking at language-laywer level is also not easy for me (Fremdsprache halt). But that actually is the problem I have with the question: at which level to answer. If you want to get a deeper understanding about the C language, I strongly encourage to read the standard (see the info page for links); it takes some time, but if you want to advance, it is worth the effort. – too honest for this site Feb 26 '16 at 23:06
  • 1
    @Olaf I started to read the standard, I will finish it soon. Danke Schön. – Michi Feb 26 '16 at 23:08
1

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.

nalzok
  • 14,965
  • 21
  • 72
  • 139
-2

You are correct, sort of. Using "initialization" to refer to both cases is confusing because there is a very important distinction.

What you refer to as the "first way" is usually called "static initialization". When you write "static int x[2]={1,2}", the compiler will generate a data block containing the values "1, 2" and then initialize X to point to the memory containing the initial values. Thus, it will always be safe to refer to x[0] in your code.

When you simply write "static int x[2]", the compiler will reserve memory for x, but you don't know what that memory is initialized to. Generally speaking, your code must write something to that memory before it uses x[0]. In a complex application or library, particularly with multiple threads, it can be tricky to make sure x has been initialized once and only once.

Static initialization is always preferable.

Tom Penny
  • 195
  • 3
  • `but you don't know what that memory is initialized to` which means that assigning something to it will initialize it? – Michi Feb 26 '16 at 23:21
  • `static int x[2];` **will be** initialised! Bad example. And there is no term "static initialisation". Just Initialiser. – too honest for this site Feb 26 '16 at 23:29
  • There is a term "static initialization", it just happens to be a C++ term (oops?) – Tom Penny Feb 26 '16 at 23:40
  • "*When you simply write "static int x[2]", the compiler will reserve memory for x, but you don't know what that memory is initialized to.*" That is just plain wrong. As of `x` is `static` all its elements will be *initialised* to `0`. – alk Oct 08 '18 at 10:56