Search code examples
cmultidimensional-arrayinitializationinitializer-list

Why the value of this matrix element is unknown?


This is a question on my exercise book:

If we write int a[][3]={{0},{1},{2}};, the value of the element a[1][2] will be ____.

The key says its value cannot be known. Since the statement are not granted to be written outside a function, the matrix should not be simply seen as a global variable, which initializes all elements to 0. However, I suppose the initializer {{0},{1},{2}} is equivalent to {{0,0,0},{1,0,0},{2,0,0}}, so a[1][2] should be 0. Who is wrong, the key or me?

PS: I wrote this code:

#include <stdio.h>

int main()
{
    int a[][3]={{0},{1},{2}};
    printf("%d",a[1][2]);
    return 0;
}

And its output is exactly 0.


Solution

  • The problem is that C has lax rules for how the braces should be interpreted, the braces do not specify how many items there are in each array. So you will end up with an array of int [3][3]; which may or may not be what you expected.

    According to the rules of array initialization, the items in each array that are not initialized explicitly, will get initialized as if they had static storage duration. That is, to zero.

    So you are correct and you can easily prove it by printing the raw contents of the memory, like this:

    #include <stdio.h>
    #include <inttypes.h>
    #include <string.h>
    
    void mem_dump (int a[3][3], size_t size);
    
    int main()
    {
      int a[][3]={{0},{1},{2}};
      printf("a is initialized like this:\n");
      mem_dump(a, sizeof(a));
      printf("\n"); 
    
      int rubbish[3][3];
      memset(rubbish, 0xAA, sizeof(rubbish)); // fill up with some nonsense character
      memcpy(a, rubbish, sizeof(a)); // a guaranteed to contain junk.
      printf("a is now filled with junk:\n");
      mem_dump(a, sizeof(a)); 
      printf("\n");
    
      memcpy(a, (int[][3]){{0},{1},{2}}, sizeof(a)); // copy back the initialized values
      printf("a now contains the initialized values once more:\n");
      mem_dump(a, sizeof(a));
    
      return 0;
    }
    
    void mem_dump (int a[3][3], size_t size)
    {
      for (size_t i=0; i<size; i++)
      {
        printf("%.2" PRIx8 " ", ((uint8_t*)a)[i] );
    
        if( (i+1) % sizeof(int[3]) == 0) // if divisible by the size of a sub array
          printf("\n");
      }
    }
    

    Output:

    a is initialized like this:
    00 00 00 00 00 00 00 00 00 00 00 00
    01 00 00 00 00 00 00 00 00 00 00 00
    02 00 00 00 00 00 00 00 00 00 00 00
    
    a is now filled with junk:
    aa aa aa aa aa aa aa aa aa aa aa aa
    aa aa aa aa aa aa aa aa aa aa aa aa
    aa aa aa aa aa aa aa aa aa aa aa aa
    
    a now contains the initialized values once more:
    00 00 00 00 00 00 00 00 00 00 00 00
    01 00 00 00 00 00 00 00 00 00 00 00
    02 00 00 00 00 00 00 00 00 00 00 00