0

So, the code only works fine, and able to print the int arr content, when i declare int arr like this :

int arr[][3] = {{2,4,6}, {8,1,7}, {2}};

but when i declare int arr[3][]

int arr[3][] = {{2,4,6}, {8,1,7}, {2}}; it shows the error above.

questions: 1. Why the 2 print on "200" ? Since it is only declared {2} in the first place on int arr[][3] = {{2,4,6}, {8,1,7}, {2}}; the output is :

246
817
200
  1. Why does the int arr[3][] = {{2,4,6}, {8,1,7}, {2}}; shows the error above ?

     #include<stdio.h>
    
     int main(int argc, char const *argv[]){
    
          int arr[3][] = {{2,4,6}, {8,1,7}, {2}};
          int i, j;
    
             for(i=0 ; i < 3 ; i++){
                 for(j=0 ; j<3 ; j++){
                     printf("%d", arr[i][j]);
             }
             printf("\n");
             }
    
                return 0;
             }
    
  • its 200 since you only set 2 to the first element and the others are initialized to 0 by the compiler you use. – Eraklon Feb 11 '20 at 14:14
  • As for the 2. question I am not sure the exact reasoning but you cannot do that. You can leave empty the first bracket from the left, but cannot the others. – Eraklon Feb 11 '20 at 14:15
  • @Eraklon why can't i leave the first bracket empty, but the second is fine ? isn't the loop just need to print either one ? – Christian Halim Feb 11 '20 at 14:24
  • 1
    Does this answer your question? [Why do we need to specify the column size when passing a 2D array as a parameter?](https://stackoverflow.com/questions/12813494/why-do-we-need-to-specify-the-column-size-when-passing-a-2d-array-as-a-parameter) – anastaciu Feb 11 '20 at 15:37
  • 1
    @anastaciu yup, that's answered my question, thanks – Christian Halim Feb 11 '20 at 16:00

1 Answers1

1

int arr[][3] = {{2,4,6}, {8,1,7}, {2}}; sets arr[2][0] to 2 explicitly. arr[2][1] and arr[2][2] are automatically set to zero—when an object is explicitly initialized but some initializers are omitted, the corresponding parts of the object are initialized as if zero had been given (null pointers for pointer types, zero for arithmetic types, and recursively so for aggregates).

In int arr[][3], the first dimension may be omitted because it is determined by counting the initializers. It is permitted to have an incomplete type temporarily, because nothing else depends on it while the compiler examines the initializers.

In int arr[3][], the second dimension may not be omitted because forming the larger array, arr[3], requires that its element type be complete. One reason for this is that it would be more work for the compiler to support an incomplete type, as explained below.

In justification of these requirements, observe that, to process the initializers of int arr[][3], all the compiler has to do is put each element of the subarray in a known place. When the compiler sees an initializer for, say, arr[i][j], where i and j are known by counting as the initializers are processed or by explicit subscript desigators (as in int arr[][3] = { [2] = { 1, 2, 3 }};, the compiler writes the initializer value to location i*3+j in the buffer where it is building the array values. Sometimes, when i increases, the compiler may need to reallocate space and copy everything to the larger space (as with realloc), but that is the only rearrangement it has to do while processing all the initializers, no matter what they are.

In contrast, consider how the compiler would have to process int arr[3][] = { … };. The compiler could read each { … } within the outer { … } and figure out which one has the greatest number of elements and make that the dimension for the array. But then it has to do one of two things:

  • it has to read all the initializers first to figure out the count, then go back and read them all again to put their values into the buffer being used to build the array, or
  • as it is building the buffer, when it discovers a subarray initialized with { … } with more elements than seen in a previous subarray, it has to rearrange most of the values in its buffer to use a new subarray size.

This is more work than we want the compiler to have to do.

Additionally, the initializers can contain expressions that cannot be evaluated if the complete type is not known, as in this atrocious code:

void *a[][3] = {  {0, 0, 0}, {&a[0][1], &a[0][2], &a[0][0]} };
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • in my code, it works if i declare using a pointer like this int *arr[][3] = {{2,4,6}, {8,1,7}, {2}}; i'm confused, does this means the code declared an array in 1 dimensional, and printing it on 2 dimensional, "%d", arr[i][j]; so how do you look the arr[i] and arr[j], basically which is the left and right ? – Christian Halim Feb 11 '20 at 14:39
  • `int arr[][3]` declares an array of arrays of 3 `int`. So `arr` is an array of arrays of 3 `int`, and `arr[i]` is an array of 3 `int`, and `arr[i][j]` is an `int`. I do not know why you bring a pointer in this. `int *arr[][3]` declares an array of arrays of 3 pointers to `int`. Then `arr[i]` is an array of 3 pointers to `int`, and `arr[i][j]` is a pointer to `int`. You would not print it with `%d`, nor would you initialize it with integers like `2`, `4`, or `6`. – Eric Postpischil Feb 11 '20 at 14:44
  • can i look at that printf("%d", arr[i][j]); on int arr[3][] = {{2,4,6}, {8,1,7}, {2}}; as basically printing these 246 817 2 on arr[i] ? since int arr[3][] ; arr[i][j] ; arr[i] is the only array containing 3 int. – Christian Halim Feb 11 '20 at 14:57