Say I have an array: array[2][4]
, and inside the main method, I have a call to a function blackandwhite
. How can I pass this method the length and width of the array as arguments?

- 6,213
- 108
- 53
- 73

- 5,739
- 11
- 37
- 45
-
1maybe `blackandwhite(array, 2, 4);`? – Oct 14 '12 at 11:13
3 Answers
This is a possible solution :
void blackandwhite(int* array, int height, int width)
{
// Array-processing done here.
// array is pointer to int,
// initially points to element myarray[0][0].
// variable height = 2;
// variable width = 4;
}
int main()
{
int myarray[2][4];
blackandwhite(&myarray[0][0], 2, 4);
}
One can find the size of an array i.e. the number of elements in it by the following construct :
int array[8];
int size = sizeof(array)/sizeof(array[0]);
Unfortunately, C arrays are native arrays and do NOT contain any metadata embedded in them. Rows and Columns are just a way of representing/accessing what is essentially linear storage space in memory. AFAIK, there is no way to automatically determine the number of rows/columns of a 2D-array, given a pointer to it (in C).
Hence one needs to pass the number of columns/rows as separate arguments along-with the pointer to the 2D-array as shown in the example above.
More info on a related question here.
UPDATE:
Common pitfall no.1 : Using int** array
in param-list
Note that a pointer to a 2 dimensional array of integers is still a pointer to a int.
int**
implies that the param refers to a pointer to a pointer to an int, which is NOT the case here.
Common pitfall no.2 : Using int[][]
in param-list
Failing to pass the dimension(s) of the array. One need NOT pass the size of the array's 1st dimension (but you may but the compiler will ignore it). The trailing dimensions are compulsory though. So,
// is INVALID!
void blackandwhite(int array[][], int height, int width)
// is VALID, 2 is ignored.
void blackandwhite(int array[2][4], int height, int width)
// is VALID.
void blackandwhite(int array[][4], int height, int width)

- 1
- 1

- 21,479
- 4
- 69
- 130
-
I understand, but could you explain why you did `int* array` in the `blackandwhite` method? – AkshaiShah Oct 14 '12 at 11:31
-
oh ok. Pointers and arrays are closely related in the sense that whenever you declare an array in C, you get a pointer of the same name (absolutely free of cost) along-with it. This pointer points to the "zero-th" element of the array. The type of pointer is the same as the type of the individual elements of the array. So in the above example as myarray(declared in main) is an array of integers, hence array(parameter declared in blackandwhite) is a pointer to an integer. – TheCodeArtist Oct 14 '12 at 11:38
-
More detailed explanation on passing arrays in C : http://stackoverflow.com/questions/1106957/pass-array-by-reference-in-c – TheCodeArtist Oct 14 '12 at 11:41
-
1You should change `blackandwhite(myarray, 2, 4)` to `blackandwhite(&myarray[0][0], 2, 4)`, else the compiler will complain – anatolyg Oct 14 '12 at 11:44
-
Also, in C the first index of a 2-D array is usually height, and the second is width; you can do whatever you want, but this version will be less confusing: `void blackandwhite(int* array, int height, int width)` – anatolyg Oct 14 '12 at 11:47
-
@anatolyg True & true. Updated the answer. It now uses an explicit pointer to the "zero-th" element of the array. This should please all C compilers. Also swapped the height-width according to common convention. – TheCodeArtist Oct 14 '12 at 11:51
If you are using a C99 compiler, or a C2011 compiler that supports variable-length arrays, you can do something like the following:
/**
* the cols parameter must be declared before it is used in
* the array parameter.
*/
void blackandwhite(size_t rows, size_t cols, int (*array)[cols])
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
array[i][j] = ...;
}
and you would call it as
int array[N][M];
...
blackandwhite(N, M, array);
In most cases1, an expression of type "N-element array of T
" will be converted ("decay") to an expression of type "pointer to T
", and the value of the expression will be the address of the first element in the array. The expression array
has type "N
-element array of M
-element array of int
"; when we pass it as a parameter to blackandwhite
, it's converted to an expression of type "pointer to M
-element array of int
", or int (*)[M]
, and its value is the same as &array[0]
.
If you are using a C2011 compiler that doesn't support variable-length arrays (VLA support is now optional), or a C89 or earlier compiler (which never supported VLAs), then you have two choices: you can either hardcode the number of columns:
void blackandwhite(size_t rows, int (*array)[M])
{
size_t i,j;
for (i = 0; i < rows; i++)
for (j = 0; j < M; j++)
array[i][j] = ...;
}
...
blackandwhite(N, array);
in which case this function will only work with arrays that have a specific number of columns, or you can use the approach shown by theCodeArtist, where you explicitly pass a pointer to the first element of the array along with the rows and columns as parameters. However, this means that you'll be treating array
as a 1D array, not a 2D array, meaning you'll have to map 2D indices onto a 1D structure:
void blackandwhite(int *array, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
array[i * rows + j] = ...; // use a 1D index
}
...
blackandwhite(&array[0][0], N, M);
Note that this approach relies on all the rows and columns of array
being contiguous in memory; if you had dynamically allocated array
such that
int **array = malloc(N * sizeof *array);
if (array)
{
size_t i;
for (i = 0; i < N; i++)
array[i] = malloc(M * sizeof *array[i]);
}
then there's no guarantee that rows are laid out contiguously in memory. However, in this specific case, you could write the following:
void blackandwhite(int **array, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
array[i][j] = ...;
}
...
blackandwhite(array, N, M);
Confused yet?
Remember that the expression a[i]
is treated as *(a + i)
; that is, we find the address of the i
th element after a
and dereference the resulting pointer value. a[i][j]
is interpreted as *(*(a+i)+j)
; *(a + i)
gives us the i
'th array following a
; by the rule mentioned above, this expression is converted from array type to pointer type, and the value is the address of the first element. We then add j
to the new pointer value and dereference the result again.
We can use array[i][j]
where array
is passed as either a pointer to an array (int (*array)[cols]
or int (*array)[M]
) or as a pointer to pointer (int **array
) because the result of array[i]
is either a pointer type or an array type that decays to a pointer type, which can have the subscript operator applied to it. We can't use array[i][j]
where array
is passed as a simple pointer to int
, because in that case the result of array[i]
is not a pointer type.
So why not do
void blackandwhite(int **array, size_t rows, size_t cols) {...}
...
int array[N][M];
blackandwhite((int **) array, N, M);
Pointers and arrays are different things, so a pointer to a pointer and a pointer to an array are different things. That would probably work, but you're lying to the compiler. Above everything else, it's bad form.
EDIT
In the context of a function parameter declaration, a parameter declaration of the form T a[]
or T a[N]
will be interpreted as T *a
; IOW, a
will be declared as a pointer, not an array. Similarly, parameter declarations of the form T a[N][M]
or T a[][M]
are treated as T (*a)[M]
; again, a
is declared as a pointer, not an array.
In our first example we could have declared blackandwhite
as
void blackandwhite(size_t rows, size_t cols, int array[rows][cols])
or
void blackandwhite(size_t rows, size_t cols, int array[][cols])
but I prefer using pointer declarations explicitly, since it correctly reflects what's happening.
1. The exceptions to this rule are when the array expression is an operand of the
sizeof
, _Alignof
, or unary &
operators, or is a string literal being used to initialize another array in a declaration, such as
char str[]="This is a test";
. 
- 119,563
- 19
- 122
- 198
In C, it is known that there is a method to calculate length of a string whereas in the case of array, you have to explicitly specify the dimensions of the array for passing length and width to the function blackandwhite
.

- 2,413
- 1
- 21
- 33