0

I am having a difficult time understanding why initializing an array with a literal size e.g. int arr[3];, yields a different behavior from an array initialized to a size of a constant like int arr[SOME_CONST]; that is set to 3.

When the size of the array is provided as a literal, it behaves as expected:

int arr[3];

//initialize the first two elements of the array, leave the third element uninitialized.
arr[0] = 1;
arr[1] = 2;


//print all elements of array
printf("arr[0]: %d\n", arr[0]);
printf("arr[1]: %d\n", arr[1]);
printf("arr[2]: %d\n", arr[2]);

Output:

arr[0]: 1
arr[1]: 2
arr[2]: 0

As you can see in the output the value of the uninitialized element arr[2] is 0 just as expected.

The behavior becomes unexpected when the array size is defined as a constant, like so:

const int SOME_CONST = 3;
int arr[SOME_CONST];

//initialize the first two elements of the array, leave the third element uninitialized.
arr[0] = 1;
arr[1] = 2;

//print all elements of array
printf("arr[0]: %d\n", arr[0]);
printf("arr[1]: %d\n", arr[1]);
printf("arr[2]: %d\n", arr[2]);

Output:

arr[0]: 1
arr[1]: 2
arr[2]: 32766

Now the uninitialized element arr[2] has a seemingly random value of 32766

Could someone help me understand why the two cases behave differently.

I've created two snippets on ideone to demonstrate this behavior as well.

Expected

Unexpected

  • 2
    Are these arrays allocated local to a function, or globally? – Steve Friedl Nov 22 '19 at 04:25
  • Both snippets are inside of `main`. – fourth_and_29 Nov 22 '19 at 05:08
  • 1
    regarding: `printf("arr[2]: %d\n", arr[2]);` since the `arr[2]` element of `int arr[3];` is not initialized, the code contains undefined behavior. here is the message from the compiler: *untitled2.c:15:2: warning: ‘arr[2]’ is used uninitialized in this function [-Wuninitialized]* When compiling, always enable the warnings, then fix those warnings. (for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) Note: other compilers use different options to produce the messages about warnings – user3629249 Nov 25 '19 at 03:00
  • Since the `arr[2]` entry is not initialized, the call to `printf()` will display what ever trash is in memory at that location – user3629249 Nov 25 '19 at 03:03

3 Answers3

5

C standard does not guarantee initialization of local variables.

Regarding the initialization statements:

arr[0] = 1;
arr[1] = 2;

Compiler can very well optimize them to this statement:

int arr[3] = {1, 2, 0};

But then I would not rely on one compilers behavior for such scenarios. Better would be to be explicit in the initialization statements.

You can refer here for similar discussion.

Also in the second scenario you are trying to use Variable Length Arrays: https://en.wikipedia.org/wiki/Variable-length_array

Which is an extension provided by GCC Compiler you are using, and I would not recommend using them in your projects.

The length of the array is computed at run-time and probably allocated on stack(depends on compiler implementation).

So it is not explicitly initialized in the code.

You can see the example here for the generated code: https://godbolt.org/z/J_JEVe

AmeyaVS
  • 814
  • 10
  • 26
3

We shouldn't bother how compiler is behaving in certain cases unless it is incorrect as per standard.

As per C standard, the uninitialized local variables can have any garbage value. Better to initialize them and don't be dependent on compiler.

Dew Kumar
  • 173
  • 2
  • 12
0

What compiler/system do you use? Maybe put your const value outside the main function. Normally both result in arbritary values taken from the stack.

rifkin
  • 339
  • 1
  • 6
  • This is the compiler version line: `gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)` – fourth_and_29 Nov 22 '19 at 06:38
  • 1
    I tried your code on my system. In both cases I get different results on every execution. So don't rely on that it is zero'ed. I tried gcc-7 gcc-8 and gcc-10. – rifkin Nov 22 '19 at 12:23