1

I am new to C language and found a problem below when I learned about array.

#include <stdio.h>
      
int main (void){
      
    int array [10];
    array [5] = 15;
      
    printf("%d\n", array[5]);
    printf("%d\n", array[9]);
    return 0;
}

In this main method, first printf method returns 15 as I initialized the value of the array.

And I expect other non-initialized value such as array[9] returns 0 but this second printf method returns random numbers such as 32764 in my WSL2 Ubuntu system.

In a tutorial video I am watching, it returns 0. What is the difference and how does this happen?

L_R
  • 170
  • 11
  • 1
    Does this answer your question? [What are all the common undefined behaviours that a C++ programmer should know about?](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a) – bolov Jun 15 '22 at 05:22
  • 4
    If the tutorial is any good it should explain to you that the values of the array are going to be unspecified if you don't set them explicitly. The array is neither initialized to zero nor to randomly generated numbers. Furthermore it should explain to you that the array only has 10 elements and that trying to access the 11th element (with index `10`) causes undefined behavior. – user17732522 Jun 15 '22 at 05:24
  • 3
    `array[10]` is _not_ in `int array [10]`. It is one past the end of the array. – chux - Reinstate Monica Jun 15 '22 at 05:24
  • 2
    An array with 10 elements starts at `array[0]` and ends at `array[9]`. `array[10]` is out of bounds. – rici Jun 15 '22 at 05:25
  • 4
    "... I expect ... non-initialized value ... returns 0" - Read your own words again, very carefully. You *know* it is not initialised, yet you *expect* a specific value. Uninitialised variables can have any value, and it may or may not be predictable what that value is. Either way, you should not access uninitialised variables. – Cheatah Jun 15 '22 at 05:30
  • Why do you think an out of bounds variable should be 0? – Jabberwocky Jun 15 '22 at 05:53
  • Please post the link to the tutorial. Then we can clear any misconceptions – Jabberwocky Jun 15 '22 at 06:01
  • @user1773252 Thank you for the comment, and accessing the 11th element was not what I meant. I changed array[10] to array[9] and it still returns 32767. Back to the question, why in my tutorial it returns 0 even though the value was unspecified and should be randomly generated value ? Is it just because 0 was the value randomly generated? – wannabeAIengineer Jun 15 '22 at 06:01
  • @wannabeAIengineer in the tutorial the 0 is not a randomly generated value, it's whatever leftover was there in memory. Local variables are not initialized to zero, the content of local variables is whatever value was there previously. In the tutorial it was 0 by chance. – Jabberwocky Jun 15 '22 at 06:04
  • @Jabberwocky Tutorial video is below and it is around 3h15min https://www.youtube.com/watch?v=UWI4ultTvI8&t=5575s – wannabeAIengineer Jun 15 '22 at 06:05
  • @Jabberwocky Thanks! Your comment made the most sense to me. I don't really get how cpu returns leftover in memory yet though. – wannabeAIengineer Jun 15 '22 at 06:09
  • 1
    the variable `array` is **uninitialized**. As such any attempt to read from it will cause Undefined Behavior. Why you get some values while on other systems it gets other values that is just the nature of Undefined Behavior: any behavior might happen: it might print garbage values, it might print `0`, it might print `hello` it might crash, it might hang. – bolov Jun 15 '22 at 06:10
  • @SupportUkraine attempting to read from an indeterminate value (except in some few specific cases) results in Undefined Behavior. The program might appear to read a value or could crash or could print "Hello World". Undefined Behavior. – bolov Jun 15 '22 at 06:44
  • 1
    @bolov That's the C++ rule. C is surprisingly a bit more relaxed on this. – user17732522 Jun 15 '22 at 06:49
  • 1
    @bolov It's not UB, it's merely unspecified behavior, assuming a mainstream system without trap representations for common types. Array access counts as taking the variable's address. See https://stackoverflow.com/a/40674888/584518. – Lundin Jun 15 '22 at 06:53
  • @user17732522 Not no surprising. C is designed to be used for low-level programming. While C++ is designed for the amusement of various language nerds in the C++ committee, none of them working with low-level programming. There are lots of other similar cases (union type punning, initialization rules, pointer aliasing, implicit heap allocation) where C++ was made needlessly unsuitable for low-level programming just because the C++ committee is filled with PC people. – Lundin Jun 15 '22 at 06:57
  • I see. I assumed it is the same in C. My bad. – bolov Jun 15 '22 at 07:31

7 Answers7

1

In C (and even more so C++) it is important to separate the terms initialization and assignment. Initialization only occurs at the line where a variable is declared. Example:

int array [10] = { [5] = 15 }; // initialization

This line could in theory perhaps be computed at program load time, on RAM based systems like PC. Assignment however, only occurs in run-time, whenever you set a value of a variable:

array[5] = 15; // assignment

The difference is important since C has lots of rules regarding what will happen when you initialize something. If you for example only initialize one item in an array, the rest of the items are guaranteed to get initialized to zero. If you don't initialize any items and the array is local ("automatic storage"), then it will contain garbage values.

Therefore your example has unspecified output since printf("%d\n", array[9]); prints an indeterminate value. It can be fixed by changing assignment into initialization as I showed:

int array [10] = { [5] = 15 };

or if you prefer, this is equivalent:

int array [10] = { 0,0,0,0,0,15 };

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

What you did was go to the hotel desk and reserver 10 rooms in a row. Now they are yours to do what you want, but this hotel doesn't have a cleaning staff. It only cares about that the rooms are not reserved, so whatever was left by the previous resident is still there.

So you saving 15 to the room #6 will clean it and put the 15 in that room, but the rest are still as you got them.

And that is not unique to arrays in anyway, all the memory you reserve is for you to take care of and manage.

Randommm
  • 410
  • 1
  • 9
0

You have not initialised array[9]. When you don't initialise any variable in C, it will contain garbage value, which can be anything and is not bound to be always 0. That's why you keep getting some random numbers.

And the person who got 0 as garbage value had his own luck.

L_R
  • 170
  • 11
0

Hy wannabeAlengineer. C is a very low language. That mean that programmer has the control of the memory.

If you declare some variable, in this case array, this array has assigned a 'n' bytes of memory. Normatly, this bytes are diferent to 0, because other programs has been executing something in the same space of memory.

If do you want to init array and all this values do you want to be 0:

int array[10] = {0};

This instruccion put all memory spaces in the array to zero.

And then, when you execut you will have that

int array[5] =15;
int array[9]=0;

Here you have the change:

#include <stdio.h>
int main (void){
//int array [10];
int array[10] = {0}; //init all to 0 values
array [5] = 15;
printf("%d\n", array[5]);
printf("%d\n", array[9]);
return 0;
}

I hope I've helped

0

And I expect other non-initialized value such as array[9] returns 0

Non-initialized variables are, well, not initialized.[1] Not to zero, not to anything else. You could get anything. It could even kill your program to use this data.

If you wanted to initialize the array elements to zero, use

int array[10] = { 0 };

(If you initialize any element of an array or structure, any elements for which no value is provided is initialized to zero. So one 0 is sufficient here.)


  1. Variables with static storage duration (globals and those declared using the static keyword) are implicitly initialized to zero if no initializer is provided.
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    Yes, it would technically have to be an exotic/fictional system with one's complement or signed magnitude to implement trap representations for `int`. Otherwise, on mainstream 2's complement system, you will get no trap but using an indeterminate value gives unspecified behavior. No crash etc though since it isn't UB in this case. In case of `int var; ... printf("%d\n",var);` you do get UB but for other reasons. – Lundin Jun 15 '22 at 09:03
  • @user17732522 I didn't say it was undefined behaviour. I said that using indeterminate values can halt your program (i.e. because of trap representations). /// Ludin, My statement was about indeterminate values in general, not just `int`s. Kudos for mentioning `int array [10] = { [5] = 15 };` in your answer. I knew you could now do that for structures, but I wasn't aware of the ability to do this for arrays. – ikegami Jun 15 '22 at 14:05
  • @ikegami Ah ok, it wasn't obvious to me that you were referring to trap representations specifically. – user17732522 Jun 15 '22 at 14:51
0

1, Uninitialized, its value has two possibilities: one is a global array, initialized to 0 by the compiler. One is a local array, which is a random number. 2, Initialized, local arrays and global arrays, initialized, unassigned arrays will be assigned a value of 0.

obsai
  • 11
0

An uninitialized array will not be equal to 0, but may be any number so you need:

int array[10] = {0};

Initialize the array to 0 and a[9] will return 0.

xjssb
  • 1
  • 1