Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why c/c++ allows omission of leftmost index of a multidimensional array in a function call?

I was just wondering why it is allowed to omit the leftmost index of a multidimensional array when passing the array to a function ? Why not more than one indexes? And how does the compiler find out the size with one index omitted ?

like image 753
vjain27 Avatar asked Apr 20 '11 23:04

vjain27


People also ask

What is the need of multidimensional array in C?

Single dimensional array only stores single data or information like marks of the student. But in some cases, you have to store complex data which have rows and columns. So, a single dimensional array can't have this type of feature. That's when a multidimensional array comes into play.

What is multidimensional array in C language?

A multi-dimensional array can be termed as an array of arrays that stores homogeneous data in tabular form. Data in multidimensional arrays are stored in row-major order. Click here for the Complete Course! The general form of declaring N-dimensional arrays is: data_type array_name[size1][size2]....

What is the correct syntax to declare a multidimensional array?

In 2-D array, to declare and access elements of a 2-D array we use 2 subscripts instead of 1. Syntax: datatype array_name[ROW][COL]; The total number of elements in a 2-D array is ROW*COL .

Why are multidimensional arrays important?

For 2D arrays, C# encourages the use of multi-dimensional arrays over jagged arrays because multi-dimensional arrays are more efficient, in terms of memory access and memory consumption.


2 Answers

Other answers described how the C standard handles array to pointer conversion and how this affects the function declaration, but I feel they didn't go into the why, so here I go...

In C, arrays stand for tightly packed elements in memory.

A -> _ _ _ _ _ _ ...
i:   0 1 2 3 4 5 ...

In the above example, each of the array elements is 1 _ wide. To find the i-th element, we thus have to go to the i-th address. (Note that the leftmost dimension (the size) doesn't matter here)

Now consider a multidimensional array:

B -> [_ _ _][_ _ _][_ _ _][_ _ _]...
i:    0 0 0  1 1 1  2 2 2  3 3 3
j:    0 1 2  0 1 2  0 1 2  0 1 2
     ^first row    ^third row

To find the offset of A[i][j] we need to jump over i rows (3*i) and then over j elements -> (3*i + j). Note how the size of the first dimension is also not needed here.

It should be clear by now then, that the leftmost size isn't needed when using the array, it is only needed when you create it.


Since there is no need to give the dimension of the leftmost index, then why not give it anyway, for completeness sake? After all, this is what is done in the Pascal programming language (a C contemporary).

Well, most functions that operate on arrays work the same for all possible array lengths, so specifying the size would only hurt your ability to reuse them.

for example, why do

int sum(int arr[10]){
    int s = 0, i;
    for(i=0; i<10; i++){
        s += arr[i];
    }
    return s;
}

When you can do this instead:

int sum(int arr[], int n){
    int s = 0, i;
    for(i=0; i<n; i++){
        s += arr[i];
    }
    return s;
}

As for omitting more then one dimension, this isn't possible when using normal multidimensional arrays (because you need to know the dimension to know when the first row ends and the second starts). However, if you are willing to spend some (little) extra memory for scratch space, it is perfectly possible to use pointers to pointers instead: http://www.eskimo.com/~scs/cclass/int/sx9b.html

like image 76
hugomg Avatar answered Sep 21 '22 07:09

hugomg


In a declaration

Actually, you can't leave out the rightmost or the leftmost dimension entirely.

However, the leftmost only can be deduced for you if you have an initialiser.

In a function argument list

When you pass an array into a function by value, you're actually passing a pointer to the first element of that array. Yes, it looks from the syntax like you're passing an array but, no, you're not.

Consider:

void f(int ar[3])

void f(int ar[])

Both are confusing syntax for the equivalent:

void f(int* ar)

No trace of an array, let alone one of specifically three elements.

Now:

void f(int ar[][3])

This is confusing syntax for the equivalent:

void f(int (*ar)[3])

where int (*)[3] is the type of a pointer to the first element of your array (pointer to int[3]).

In conclusion, don't pay too much attention to the array-like syntax that looks like []; it's not really representative of what's truly happening.

like image 20
Lightness Races in Orbit Avatar answered Sep 20 '22 07:09

Lightness Races in Orbit