0

I'd like to know why the printf function in this tiny program returns 0 instead of the array of numbers 3 2 2:

int main(){
    int mat[2][2][2] = {{3,1,1},{2,2,2}};

    printf("first x, 2nd y, 2nd z = %d\n",mat[0][1][1]);
}

While working with X by Y matrices in C retrieving any value XxY was a breeze, but once I added another dimension I ran into this problem. I think I must've a misunderstanding of the way C deals with coordinates in arrays. Thanks a lot!

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
JayRyne
  • 3
  • 2

5 Answers5

1

In

int mat[2][2][2] = {{3,1,1},{2,2,2}};

you declare a 3D array but you give initialization for a 2D, the values are not placed where you expect

#include <stdio.h>

int main(){
  int mat[2][2][2] = {{3,1,1},{2,2,2}};

  for (int i = 0; i != 2; ++i)
    for (int j = 0; j != 2; ++j)
      for (int k = 0; k != 2; ++k)
        printf("%d %d %d -> %d\n", i, j, k, mat[i][j][k]);
  return 0;
}

Execution : pi@raspberrypi:/tmp $ ./a.out

0 0 0 -> 3
0 0 1 -> 1
0 1 0 -> 1
0 1 1 -> 0
1 0 0 -> 2
1 0 1 -> 2
1 1 0 -> 2
1 1 1 -> 0
pi@raspberrypi:/tmp $ 

Furthermore because your array has 8 int but the init value has only 6 the compiler initializes the two not specified entries with 0

bruno
  • 32,421
  • 7
  • 25
  • 37
1

The problem is that this array element mat[0][1][1] does not have an explicit initializer. So it was zero-initialized.

Then you have such a declaration

int mat[2][2][2] = {{3,1,1},{2,2,2}};

then the first element of the array mat[0] as an aggregate is initialized by this list { 3, 1, 1 } and the second element of the array mat[1] is initialized by this list { 2, , 2, 2 }.

As for elements of the element mat[0] that are in turn aggregates braces are not specified then the elements of mat[0] are initialized sequentially like

mat[0][0][0] = 3
mat[0][0][1] = 1
mat[0][1][0] = 1 

All other elements of the element (array) mat[0] are zero initialized.

Here is a demonstrative program.

#include <stdio.h>

int main(void) 
{
    int a[2][2][2] = {{3,1,1},{2,2,2}};

    printf( "%d, %d, %d\n", a[0][0][0], a[0][0][1], a[0][1][0] );
    printf( "%d, %d, %d\n", a[1][0][0], a[1][0][1], a[1][1][0] );

    return 0;
}

Its output is

3, 1, 1
2, 2, 2
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

This code will give you why your result is 0:

int main(){
    int mat[2][2][2] = {{3,1,1},{2,2,2}};

    for(int i = 0; i < 2; i++)
         for(int j = 0; j < 2; j++)
             for(int k = 0; k < 2; k++)
                 printf("mat[%d][%d][%d] = %d \n", i, j, k, mat[i][j][k]);
   return 0;
}

output:

mat[0][0][0] = 3                                                                                                          
mat[0][0][1] = 1                                                                                                          
mat[0][1][0] = 1                                                                                                          
mat[0][1][1] = 0                                                                                                          
mat[1][0][0] = 2                                                                                                          
mat[1][0][1] = 2                                                                                                          
mat[1][1][0] = 2                                                                                                          
mat[1][1][1] = 0 

When you declare:

int mat[2][2][2] = {{3,1,1},{2,2,2}};

it means you are lying at program that it's 2D array, not 3D.

Hitokiri
  • 3,607
  • 1
  • 9
  • 29
0

You have a 3-dimensional array, but you're initializing a 2 level array with 1 extra value. Consider something like:

#include <cstdio>

int main(){
    int mat[2][2][2] = {
       {{3, 3}, {1, 1}},
       {{1, 1}, {1, 1}}
    };

    printf("first x, 2nd y, 2nd z = %d\n", mat[0][1][1]);
}
LZR
  • 948
  • 10
  • 28
0

You've specified an array with three dimensions, but only specified two. Furthermore, each element is supposed to have two entries, but you've got three.

If you turn on warnings you should see warnings like these:

test.c:4:26: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    int mat[2][2][2] = {{3,1,5},{2,2,2}};
...more like that...
test.c:6:44: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
    printf("z for first coordinate = %d\n",mat[0][2]);
                                     ~~    ^~~~~~~~~
test.c:6:44: warning: array index 2 is past the end of the array (which contains 2 elements)
      [-Warray-bounds]
    printf("z for first coordinate = %d\n",mat[0][2]);
                                           ^      ~
test.c:4:5: note: array 'mat' declared here
    int mat[2][2][2] = {{3,1,5},{2,2,2}};
    ^

int mat[2][2][2] would initialize like this.

int mat[2][2][2] = {
    {
        {3,1}, {1,1},
    },
    {
        {1,1}, {2,2},
    }
};

You'll never get 3 2 2 from mat[0][1][1]. It will only ever return a single value. In this case, 1.


If you wish to store a list of 2 3D coordinates, use [2][3] instead.

int mat[2][3] = {{3,1,1},{2,2,2}};

Asking what z is for the first x and second y doesn't make sense. It's like asking what the altitude of Denver, New Jersey is (Denver is in Colorado). First x and second y are part of two different coordinates and have different z's.

Instead, you can get the z for the first coordinate like so.

printf("z for first coordinate = %d\n",mat[0][2]);

The first coordinate is mat[0] and its z is the 3rd attribute which is the 2nd index. mat[0][2].

Schwern
  • 153,029
  • 25
  • 195
  • 336