2

Im really puzzled by this code. What I have is

int main(){
 int *array[6];
 for (int i = 0; i < 6; i++){
  if (array[i]==NULL){
   printf("NULL\n");
  }
 }
}

Can anyone explain why my code is printing NULL only once? I thought that this would print NULL 6 times.

Meeoh
  • 463
  • 4
  • 11
  • Why would you think that? Justify your thinking first. – abelenky Mar 03 '15 at 19:58
  • Going back it would make more sense for it not to print NULL any times. Since normally declaring an array with no elements sets all the values to undefined. – Meeoh Mar 04 '15 at 00:20
  • Possible duplicate of [What happens to a declared, uninitialized variable in C? Does it have a value?](https://stackoverflow.com/questions/1597405/what-happens-to-a-declared-uninitialized-variable-in-c-does-it-have-a-value) – phuclv Mar 16 '19 at 02:01
  • [Is un-initialized integer always default to 0 in c?](https://stackoverflow.com/q/6212921/995714) – phuclv Mar 16 '19 at 02:01

4 Answers4

6

Because you didn't initialize array elements. Their value is unspecified if not initialized.

Use:

int *array[6] = {0};

to initialize all array elements to a null pointer constant.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    I know that their value is unspecified if not initialized, which means really the array just holds a whole lot of garbage right. Im wondering why the 0'th element is always NULL, even though its not specified – Meeoh Mar 03 '15 at 19:45
  • @ShameelAbdullah unspecified means it could be `42`, `314159` or even `0`. If your run your program later, you may have a totally different behavior. – ouah Mar 03 '15 at 20:02
  • Yeah thats what I mean, I've ran it many times, and its always one printout of NULL – Meeoh Mar 03 '15 at 20:03
  • 1
    @ShameelAbdullah on another system, or on your system but another day, or on your system with a different number of processes running, you may get a different behavior. That's the principle of unspecified. – ouah Mar 03 '15 at 20:05
1

C (in contrast to some other languages) doesn't assign a default value to members of an array, so the number of times your program outputs NULL is undefined.

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
Axel
  • 13,939
  • 5
  • 50
  • 79
  • Is it just a coincidence that it is consistently 1 every time I run the program? – Meeoh Mar 03 '15 at 19:48
  • @ShameelAbdullah: Yes. It's undefined behavior to access the value of an object that is in an indeterminate state (C99§Annex J.2), so your compiler may have performed an optimization that resulted in a program that behaves consistently, but incorrectly. It's also possible that your OS is reusing resources, resulting the same garbage values with each run of the program (but I think that's less likely). – Slade Mar 03 '15 at 19:56
  • @Axel "so the number of times your program outputs NULL is undefined." Technically, the behavior of the entire program is undefined. – Slade Mar 03 '15 at 20:06
1

According to C Standard (6.7.9 Initialization)

10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then: — if it has pointer type, it is initialized to a null pointer;

Thus in your program

int main(){
 int *array[6];
 for (int i = 0; i < 6; i++){
  if (array[i]==NULL){
   printf("NULL\n");
  }
 }
}

array array can contain any values. However if you will rewrite your program the following way

int main(){
 static int *array[6];
 for (int i = 0; i < 6; i++){
  if (array[i]==NULL){
   printf("NULL\n");
  }
 }
}

or

int *array[6];

int main(){
 for (int i = 0; i < 6; i++){
  if (array[i]==NULL){
   printf("NULL\n");
  }
 }
}

then all elements of the array will be initialized by NULL.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1


The fact that you get one, and always one NULL value is due to the content of the stack, which depends on the code executed before your main gets called, which in turn depends on the compiler/libc you are using, and on the compilation options. But once compiled, running the programm any number of times will always get you the same values. As stated in other answers, this is because you did not explicitely initialise the array and it's scope (local to the function) allows the compiler to place it on the stack, where it gets the content of what was there before the call to main.

To get 6 NULL pointers, you should either explicitely initialize the array (int *array[6] = {0};) or make it static or global.

In the later cases, the compiler will place the array in the bss section (data section which is not present in the binary, but which get allocated and initialised to zeroes by the libc before calling your main() function).

In the first case (local array initialised to 0) the compiler can now make optimisations, as the value is known and never modified, and will certainly remove both the array and the test and simply call printf 6 times.

Compiled with another compiler, or with different optimisation levels (-O2, -O3) will gave you a different result, but still consistent (if not identical) between each calls.

Anyway, regardless of initializing your array, you should fix your code regarding to the respect of C standard : your main must return a value, and ‘for’ loop initial declarations are only allowed in C99 mode, so you should get this :

#include <stdio.h>
int main(){
    int* array[6];
    int i = 0;
    for (i = 0; i < 6; i++) {
        if (array[i] == NULL) {
            printf("%d NULL\n", i);
        }
    }
    return 0;
}

I added display of the position number of the NULL value, to show that it's always the same one. You can even add an else statement, and print the values when not NULL :

        } else {
            printf("%d %p\n", i, array[i]);

And you will get something like this :

$ ./test
0 NULL
1 0x4011cd
2 0x7f8d2fdf64c0
3 NULL
4 0x4011a0
5 0x401050

$ ./test
0 NULL
1 0x4011cd
2 0x7fa96155e4c0
3 NULL
4 0x4011a0
5 0x401050

I could run it 1000 times, values for 0, 1, 3, 4 and 5 are always the same ones. Only the value for number 2 changes, which I think means that it is used to store an address.

One could get exact information by reading the output of objdump -D and analyzing the code generated by GCC.

Nathael Pajani
  • 111
  • 1
  • 2