Introduction
Arrays are the built-in containers of C and C++. This article assumes the reader has some experiece with
arrays and array syntax but is not clear on a )exactly how multi-dimensional arrays work, b) how to call
a function with a multi-dimensional array, c) how to return a multi-dimensional array from a function,
or d) how to read and write arrays from a disc file.
Note to C++ programmers: You should be using vectors instead of arrays. The protective code you need
to write around your array is a duplication of the protective code written around the array in the STL.
The STL just calls their array plus managing code a vector.
Note to C programmers: Everything in this article conforms to ANSI-C with the exception of heap allocations.
The examples use the C++ new operator where a C programmer would call malloc().
How to Define Arrays
First, there are only one-dimensional arrays in C or C++. The number of elements is put between brackets:
Expand|Select|Wrap|Line Numbers
- int array[5];
Expand|Select|Wrap|Line Numbers
- int array[];
Second, this array:
Expand|Select|Wrap|Line Numbers
- int array[5][10];
Expand|Select|Wrap|Line Numbers
- int array[5][10][15];
Expand|Select|Wrap|Line Numbers
- int array[][10];
Third, the name of an array is the address of element 0
Expand|Select|Wrap|Line Numbers
- int array[5];
Expand|Select|Wrap|Line Numbers
- int array[5][10];
Expand|Select|Wrap|Line Numbers
- int array[5][10];
- int (*ptr)[10] = array;
Expand|Select|Wrap|Line Numbers
- int* array = new int[value];
- int (*ptr)[10] = new int[value][10];
- int (*ptr)[10][15] = new int[value][10][15];
Using an int** for an array of arrays is incorrect and produces wrong answers using pointer arithmetic. The compiler knows this so it won't compile this code:
Expand|Select|Wrap|Line Numbers
- int** ptr = new int[value][10]; //ERROR
Likewise:
Expand|Select|Wrap|Line Numbers
- int*** ptr = new int[value][10][15]; //ERROR
With the above in mind this array:
Expand|Select|Wrap|Line Numbers
- int array[10] = {0,1,2,3,4,5,6,7,8,9};
0 1 2 3 4 5 6 7 8 9
Wheras this array:
Expand|Select|Wrap|Line Numbers
- int array[5][2] = {0,1,2,3,4,5,6,7,8,9};
0 1 2 3 4 5 6 7 8 9
Kinda the same, right?
So if your disc file contains
0 1 2 3 4 5 6 7 8 9
Does it make a difference wheher you read into a one-dimensional array or a two-dimensional array? No.
Therefore, when you do your read use the address of array[0][0] and read as though you have a
one-dimensional array and the values will be in the correct locations.
Passing Multi-dimensional Arrays to Functions
This array:
Expand|Select|Wrap|Line Numbers
- int arr[3][4][5];
can be passed to a function if the argument to func() is a pointer to a [4][5] array:
Expand|Select|Wrap|Line Numbers
- void func(int (* arg)[4][5], unsigned int x);
- int main()
- {
- int arr[3][4][5];
- func(arr, 3);
- }
Expand|Select|Wrap|Line Numbers
- void func(int (* arg)[5], unsigned int x, int y);
- int main()
- {
- int arr[3][4][5];
- func(&arr[0][0], 3, 4);
- }
Expand|Select|Wrap|Line Numbers
- void func(int * arg, unsigned int x, int y, int z);
- int main()
- {
- int arr[3][4][5];
- func(&arr[0][0][0], 3, 4, 5);
- }
lost on the call. This is called decay of array and it occurs whenever an array is passed
to a function. From inside the function all you see is an address and not an array. That forces you to pass
the number of elements in the "dimensions".
Returning Multi-dimensional Arrays from Functions
Returning an array from a function only has meaning if the array was created by the function. Otherwise,
no return is necessary since an existing array is passed by the address. However, if the function has
created the array on the heap, you can return the address of element 0.
The problem here is that you can't use the function return type unless you a) return a type or
b) return a pointer to a type. That is, you cannot return a pointer to an array since an array is not
a type. So, if you create an array of int you can return the array as an int*:
Expand|Select|Wrap|Line Numbers
- int* func(int arg)
- {
- int* temp = new int[arg];
- return temp;
- }
- int main()
- {
- int* arr = func(5);
- }
Expand|Select|Wrap|Line Numbers
- int (*)[5] func(int arg) // ERROR: Cannot return an array
- {
- int (* temp)[5] = new int[arg][5];
- return temp;
- }
- int main()
- {
- int (* arr)[5] = func(4);
- }
Expand|Select|Wrap|Line Numbers
- void func(int arg, int (**rval)[5])
- {
- int (* temp)[5] = new int[arg][5];
- *rval = temp;
- }
- int main()
- {
- int (* arr)[5] = 0;
- func(4, &arr);
- //arr is now a [4][5] array of int
- }
Expand|Select|Wrap|Line Numbers
- typedef int (*IntArray5Ptr)[5];
Expand|Select|Wrap|Line Numbers
- IntArray5Ptr func(int arg)
- {
- int (* temp)[5] = new int[arg][5];
- return temp;
- }
- int main()
- {
- int (* arrA)[5] = func(4);
- }
Expand|Select|Wrap|Line Numbers
- typedef int IntArray5[5];
- IntArray5* funcB(int arg)
- {
- int (* temp)[5] = new int[arg][5];
- return temp;
- }
- int main()
- {
- int (* arr)[5] = func(4);
- }
Therefore, a function could just create a one-dimensional array of the correct number of elements and return
the address of element 0. In this case, element 0 is a type and you can use the return type of a function
to return a pointer to a type. Then the calling function could typecast the return so the array can be
used with muliple dimensions:
Expand|Select|Wrap|Line Numbers
- int* func(int arg)
- {
- int * temp = new int[arg];
- return temp;
- }
- int main()
- {
- //This is arr[60]
- int* arr = func(60);
- //This is arr[12][5] --> 12 x 5 = 60
- int (*arr1)[5] = (int(*)[5])func(60);
- //This is arr[3][4][5] -> 3 * 4 * 5 = 60
- int (*arr2)[4][5] = (int(*)[4][5])func(60);
- //This is arr[1][3][4][5] -> 1*3*4*5 = 60;
- int (*arr3)[3][4][5] = (int(*)[3][4][5])func(60);
- }
2010/04/11 - Added examples of returning a multi-dimensional array from an RVAL function.
Copyright 2010 Buchmiller Technical Associates North Bend WA USA