How to generalize plain 2D arrays? - c++

For C++, I have seen several recommendations to use a 2D arrays as follows:
int* theArray = new int[d1 * d2];
An element (i, j) can then be accessed as follows:
int myInt = theArray[i + d2 * j];
I have two questions: First, how to access a 3D array? Is there a general formula? Second and more important, will there be a performance penalty if I use functions
int getNumber(int i, int j, int k)
void setNumber(int i, int j, int k, int theValue)
to retrieve and set number? I don't want to screw it up somewhere in the code and then spend forever finding where that screw up is.

Generalization to three dimension is not difficult:
int* theArray = new int[d1*d2*d3];
and accessing it using
int myInt = theArray[i+d1*(j+d2*k)];
Just like decimal system for example. When you write 123 as 3+10*2+100*3 = 3 + 10*(2+10*3). Where 10 is the size of each dimension. Note that I have changed your d2 to d1, as what is indented is the size of the dimension associated to the index i.
Regarding your second question, the function called can reduce the performances. But you can avoid this issue by inlining the function, or defining a macro, which is then equivalent to no function call at all, regarding performance.

I'd say for 2D array, assuming i is the first index and j is the second, it's better to do indexing like
int myInt = theArray[i*d2 + j];
so changing the last index gives you contiguous range. This is how C and C++ multi-dimensional arrays are implemented.
So if your 3D array is
int* theArray = new int[d1*d2*d3];
Then you access it this way:
int myInt = theArray[(i*d2 + j)*d3 + k];
Regarding accessor functions - if they are inline, the overhead will be zero. You may want also to wrap this all into your custom array class (but that's probably what you are already intending to do)

To see how this is solved in a more general way, you can have a look at boost multi_array.

I would go with std::array instead and not do any manual index calculations. Just make sure that the last index is the one you will most likely loop over. std::array is as fast as [].
#include <iostream>
#include <array>
int main() {
constexpr size_t a=5;
constexpr size_t b=4;
constexpr size_t c=3;
std::array<std::array<std::array<float,a>, b>, c> arr3d;
for(auto& outer : arr3d){
for(auto& row : outer){
for(auto& place : row){
place=3.5;
}
}
}
for(size_t i=0;i<a; ++i){
for(size_t j=0;j<b; ++j){
for(size_t k=0;k<c; ++k){
arr3d[i][j][k]=k; // or whatever
}
}
}
std::cout << arr3d[0][1][2] << std::endl;
}
If you need run-time flexibility for the sizes, use std::vector.
template<typename T> using Vec = std::vector<T>;
Vec<Vec<Vec<float>>> arr3d(a,Vec<Vec<float>>(b,Vec<float>(c,0)));
but it is going to be significantly slower to initialize and depending on how you use it (and the values of a,b,c) access will be slower also. (note comments).
For other ways to initialize the array: Other ways to initialize the array

Related

Dynamic array of Linear search funcion implementation

Need to implement a function
int* linearSearch(int* array, int num);
That gets a fixed size array of integers with a number and return an array with indices to the occurrences of the searched number.
For example array={3,4,5,3,6,8,7,8,3,5} & num=5 will return occArray={2,9}.
I've implemented it in c++ with a main function to check the output
#include <iostream>
using namespace std;
int* linearSearch(int* array, int num);
int main()
{
int array[] = {3,4,5,3,6,8,7,8,3,5}, num=5;
int* occArray = linearSearch(array, num);
int i = sizeof(occArray)/sizeof(occArray[0]);
while (i>0) {
std::cout<<occArray[i]<<" ";
i--;
}
}
int* linearSearch(int* array, int num)
{
int *occArray= new int[];
for (int i = 0,j = 0; i < sizeof(array) / sizeof(array[0]); i++) {
if (array[i] == num) {
occArray[j] = i;
j++;
}
}
return occArray;
}
I think the logic is fine but I have a syntax problems with creating a dynamic cell for occArray
Also a neater implantation with std::vector will be welcomed
Thank You
At very first I join in the std::vector recommendation in the question's comments (pass it as const reference to avoid unnecessary copy!), that solves all of your issues:
std::vector<size_t> linearSearch(std::vector<int> const& array, int value)
{
std::vector<size_t> occurrences;
// to prevent unnecessary re-allocations, which are expensive,
// one should reserve sufficient space in advance
occurrences.reserve(array.size());
// if you expect only few occurrences you might reserve a bit less,
// maybe half or quarter of array's size, then in general you use
// less memory but in few cases you still re-allocate
for(auto i = array.begin(); i != array.end(); ++i)
{
if(*i == value)
{
// as using iterators, need to calculate the distance:
occurrences.push_back(i - array.begin());
}
}
return occurences;
}
Alternatively you could iterate with a size_t i variable from 0 to array.size(), compare array[i] == value and push_back(i); – that's equivalent, so select whichever you like better...
If you cannot use std::vector for whatever reason you need to be aware of a few issues:
You indeed can get the length of an array by sizeof(array)/sizeof(*array) – but that only works as long as you have direct access to that array. In most other cases (including passing them to functions) arrays decay to pointers and these do not retain any size information, thus this trick won't work any more, you'd always get sizeOfPointer/sizeOfUnderlyingType, on typical modern 64-bit hardware that would be 8/4 = 2 for int* – no matter how long the array originally was.
So you need to pass the size of the array in an additional parameter, e.g.:
size_t* linearSearch
(
int* array,
size_t number, // of elements in the array
int value // to search for
);
Similarly you need to return the number of occurrences of the searched value by some means. There are several options for:
Turn num into a reference (size_t& num), then you can modify it inside the function and the change gets visible outside. Usage of the function get's a bit inconvenient, though, as you need to explicitly define a variable for:
size_t num = sizeof(array)/sizeof(*array);
auto occurrences = linearSearch(array, num, 7);
Append a sentinel value to the array, which might be the array size or probably better maximum value for size_t – with all the disadvantages you have with C strings as well (mainly having to iterate over the result array to detect the number of occurences).
Prepend the number of occurrences to the array – somehow ugly as well as you mix different kind of information into one and the same array.
Return result pointer and size in a custom struct of yours or in e.g. a std::pair<size_t, size_t*>. You could even use that in a structured binding expression when calling the function:
auto [num, occurences] = linearSearch(array, sizeof(array)/sizeof(*array), 7);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// here the trick yet works provided the array is declared above the call, too,
// as is in your example
Option 4 would be my personal recommendation out of these.
Side note: I switched to size_t for return values as negative indices into an array are meaningless anyway (unless you intend to use these as sentinel values, e. g. -1 for end of occurrences in option 2).

passing a multidimensional array to a function with argument of type double *

I am using a library that takes a pointer to a double array as an argument, called as follows:
const int N=10;
const int J=20;
double my_array[N*J];
libFunc(my_array, N, J);
I would prefer to work with multidimensional arrays in my code, and I have discovered that I can call libFunc by dereferencing my multidimensional double array as follows
double my_array2[N][J];
libFunc(&my_array2[0][0], N, J);
However, I am worried that this code might not be portable, that it may not continue to work as N and M get large, and that there may be other hidden problems.
Why is this bad, what should I look out for here? What is the proper way to use multidimensional arrays and pass them to libFunc as if they were ordinary double arrays?
Edit: Read the comments below the selected answer for a discussion of the issue at hand. It seems that if I declare a static array, as is done above, then this code should work on most compilers. However if the array is dynamically allocated there may be an issue.
There is no simple way short of making a copy. Accessing an array outside its bounds is undefined behaviour, and you won't get around this.
Now, it is possible in many situations that your code works, simply because the memory for T[M * N] and for T[M][N] is laid out in the same way. As long as the caller and the callee aren't visible to the compiler at the same time, I would hazard a guess that this should work.
But imagine this scenario:
T a[M][N];
for (size_t i = 0; i != M * N; ++i)
{
a[0][i] = 0;
}
Here the compiler may reason that a[0][N] is out of bounds, and thus there is undefined behaviour, and the compiler may legally omit the entire loop, or make the application crash or wipe your hard disk.
So... take your pick. Undefined behaviour is around somewhere, but you might get lucky.
You are basically screwed: The function expects a double *, so you should give it a double *.
The easiest and safer way to do that would be to use a wrapper. Something like:
template<size_t M, size_t N>
class Double2DArray
{
std::vector<double> m_container ; // It could be a double[M * N]
// But it could explode your stack
// So let's use the heap
public :
// Etc.
Double2DArray()
: m_container(M * N)
{
// I assume the default you want is a vector already
// filled with 0.0
}
size_t getSizeM() { return M ; }
size_t getSizeN() { return N ; }
double & operator() (size_t p_m, size_t p_n)
{
return m_container[p_m * N + p_n] ;
}
double * data()
{
return &(m_container[0]) ;
}
// etc.
} ;
Of course, this code is not complete: At the very least, you should add the const versions of the accessors, probably handle copy-construction and assignment, etc.. I don't know your exact needs, so, your mileage may vary, but the core idea is there...
You could use this wrapper as follow:
void foo()
{
Double2DArray<42, 13> my2DArray ;
// etc.
my2DArray(3, 5) = 3.1415 ; // set some value
double d = my2DArray(13, 2) ; // get some value
// etc.
libFunc(my2DArray.data(), my2DArray.getSizeM(), my2DArray.getSizeN());
}
I would even overload libFunc to be safer:
template<size_t M, size_t N>
inline void libFunc(Double2DArray<M, N> & p_my2DArray)
{
libFunc(p_my2DArray.data(), M, N);
}
This way I could be able to call it without needed to give it again and again the size of the array (it's so easy to mix M and N):
void foo()
{
Double2DArray<42, 13> my2DArray ;
// etc.
libFunc(my2DArray);
}
This is how I would use multidimensional arrays and feed it to a C-like API expected a contiguous array of doubles.
P.S.: If M and N are not know at compile time, you only need to remove the template, and make the M and N parameters of the constructor, and everything works (almost) the same.
C++ uses row-major ordering so your multidimensional array is in fact a continuous 1-dimensional region in memory.
Even if declared for example 2-dimensional, it's accessed via index = x + y * height, so there should be no portability concerns...
The C++ documentation tells:
Multidimensional arrays are just an abstraction for programmers, since
we can obtain the same results with a simple array just by putting a
factor between its indices
(Here's also an explaination for visual c++)

elegant way to create&pass multi-dimensional array in c++?

first question:
for known dimensions, we don't need new/malloc for the creation
const int row = 3;
const int col = 2;
int tst_matrix[row][col] ={{1,2},{3,4},{5,6}}
however, there is no easy to pass this two-dimensional array to another function, right? because
int matrix_process(int in_matrix[][])
is illegal, you have to specify all the dimensions except the first one. if I need to change the content of in_matrix, how could I easily pass tst_matrix to the function matrix_process?
second question:
what's the standard way to create 2-dimensional array in c++ with new? I dont wanna use std::vector etc.. here.
here is what I come up with, is it the best way?
int **tst_arr = new int*[5];
int i=0, j=0;
for (i=0;i<5;i++)
{
tst_arr[i] = new int[5];
for (j=0;j<5;j++)
{
tst_arr[i][j] = i*5+j;
}
}
In addition, if I pass tst_array to another function, like:
int change_row_col( int **a)
{
.....................
//check which element is 0
for (i=0; i<5; i++)
for(j=0;j<5;j++)
{
if (*(*(a+i)+j)==0) //why I can not use a[i][j] here?
{
row[i]=1;
col[j]=1;
}
}
.....................
}
In addition, if I use ((a+i)+j), the result is not what I want.
Here is the complete testing code I had:
#include <iostream>
using namespace std;
//Input Matrix--a: Array[M][N]
int change_row_col( int **a)
{
int i,j;
int* row = new int[5];
int* col = new int[5];
//initialization
for(i=0;i<5;i++)
{
row[i]=0;
}
for(j=0;j<5;i++)
{
col[j]=0;
}
//check which element is 0
for (i=0; i<5; i++)
for(j=0;j<5;j++)
{
if (*(*(a+i)+j)==0) //why I can not use a[i][j] here?
{
row[i]=1;
col[j]=1;
}
}
for(i=0;i<5;i++)
for (j=0;j<5;j++)
{
if (row[i] || col[j])
{
*(*(a+i)+j)=0;
}
}
return 1;
}
int main ()
{
int **tst_arr = new int*[5];
int i=0, j=0;
for (i=0;i<5;i++)
{
tst_arr[i] = new int[5];
for (j=0;j<5;j++)
{
tst_arr[i][j] = i*5+j;
}
}
for (i=0; i<5;i++)
{
for(j=0; j<5;j++)
{
cout<<" "<<tst_arr[i][j];
}
cout<<endl;
}
change_row_col(tst_arr);
for (i=0; i<5;i++)
{
for(j=0; j<5;j++)
{
cout<<" "<<tst_arr[i][j];
}
cout<<endl;
}
for (i=0;i<5;i++)
{
delete []tst_arr[i];
}
delete []tst_arr;
}
For multidimensional arrays were all the bounds are variable at run time, the most common approach that I know of is to use a dynamically allocated one dimensional array and do the index calculations "manually". In C++ you would normally use a class such as a std::vector specialization to manage the allocation and deallocation of this array.
This produces essentially the same layout as a multidimensional array with fixed bounds and doesn't have any real implied overhead as, without fixed bounds, any approach would require passing all bar one of the array dimensions around at run time.
I honestly think the best idea is to eschew raw C++ arrays in favor of a wrapper class like the boost::multi_array type. This eliminates all sorts of weirdness that arises with raw arrays (difficulty passing them S parameters to functions, issues keeping track of the sizes of the arrays, etc.)
Also, I strongly urge you to reconsider your stance on std::vector. It's so much safer than raw arrays that there really isn't a good reason to use dynamic arrays over vectors in most circumstances. If you have a C background, it's worth taking the time to make the switch.
My solution using function template:
template<size_t M,size_t N>
void Fun(int (&arr)[M][N])
{
for ( int i = 0 ; i < M ; i++ )
{
for ( int j = 0 ; j < N ; j++ )
{
/*................*/
}
}
}
1)
template < typename T, size_t Row_, size_t Col_>
class t_two_dim {
public:
static const size_t Row = Row_;
static const size_t Col = Col_;
/* ... */
T at[Row][Col];
};
template <typename T>
int matrix_process(T& in_matrix) {
return T::Row * T::Col + in_matrix.at[0][0];
}
2) use std::vector. you're adding a few function calls (which may be inlined in an optimized build) and may be exporting a few additional symbols. i suppose there are very good reasons to avoid this, but appropriate justifications are sooooo rare. do you have an appropriate justification?
The simple answer is that the elegant way of doing it in C++ (you tagged C and C++, but your code is C++ new/delete) is by creating a bidimensional matrix class and pass that around (by reference or const reference). After that, the next option should always be std::vector (and again, I would implement the matrix class in terms of a vector). Unless you have a very compelling reason for it, I would avoid dealing with raw arrays of arrays.
If you really need to, but only if you really need to, you can perfectly work with multidimensional arrays, it is just a little more cumbersome than with plain arrays. If all dimensions are known at compile time, as in your first block this are some of the options.
const unsigned int dimX = ...;
const unsigned int dimY = ...;
int array[dimY][dimX];
void foo( int *array[dimX], unsigned int dimy ); // [1]
void foo( int (&array)[dimY][dimX] ); // [2]
In [1], by using pass-by-value syntax the array decays into a pointer to the first element, which means a pointer into an int [dimX], and that is what you need to pass. Note that you should pass the other dimension in another argument, as that will be unknown by the code in the function. In [2], by passing a reference to the array, all dimensions can be fixed and known. The compiler will ensure that you call only with the proper size of array (both dimensions coincide), and thus no need to pass the extra parameter. The second option can be templated to accomodate for different sizes (all of them known at compile time):
template <unsigned int DimX, unsigned int DimY>
void foo( int (&array)[DimY][DimX] );
The compiler will deduct the sizes (if a real array is passed to the template) and you will be able to use it inside the template as DimX and DimY. This enables the use of the function with different array sizes as long as they are all known at compile time.
If dimensions are not known at compile time, then things get quite messy and the only sensible approach is encapsulating the matrix in a class. There are basically two approaches. The first is allocating a single contiguous block of memory (as the compiler would do in the previous cases) and then providing functions that index that block by two dimensions. Look at the link up in the first paragraph for a simple approach, even if I would use std::vector instead of a raw pointer internally. Note that with the raw pointer you need to manually manage deletion of the pointer at destruction or your program will leak memory.
The other approach, which is what you started in the second part of your question is the one I would avoid at all costs, and consists in keeping a pointer into a block of pointers into integers. This complicates memory management (you moved from having to delete a pointer into having to delete DimY+1 pointers --each array[i], plus array) and you also need to manually guarantee during allocation that all rows contain the same number of columns. There is a substantial increase in the number of things that can go wrong and no gain, but some actual loss (more memory required to hold the intermediate pointers, worse runtime performance as you have to double reference, probably worse locality of data...
Wrapping up: write a class that encapsulates the bidimensional object in terms of a contiguous block of memory (array if sizes are known at compile time --write a template for different compile time sizes--, std::vector if sizes are not known until runtime, pointer only if you have a compelling reason to do so), and pass that object around. Any other thing will more often than not just complicate your code and make it more error prone.
For your first question:
If you need to pass a ND array with variable size you can follow the following method to define such a function. So, in this way you can pass the required size arguments to the function.
I have tested this in gcc and it works.
Example for 2D case:
void editArray(int M,int N,int matrix[M][N]){
//do something here
}
int mat[4][5];
editArray(4,5,mat); //call in this way

Passing array with unknown size to function

Let's say I have a function called MyFunction(int myArray[][]) that does some array manipulations.
If I write the parameter list like that, the compiler will complain that it needs to know the size of the array at compile time. Is there a way to rewrite the parameter list so that I can pass an array with any size to the function?
My array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).
What if I could convert the array to a vector and then pass the vector to MyFunction? Is there a one-line conversion that I can use or do I have to do the conversion manually?
In C++ language, multidimensional array declarations must always include all sizes except possibly the first one. So, what you are trying to do is not possible. You cannot declare a parameter of built-in multidimensional array type without explicitly specifying the sizes.
If you need to pass a run-time sized multidimensional array to a function, you can forget about using built-in multidimensional array type. One possible workaround here is to use a "simulated" multidimensional array (1D array of pointers to other 1D arrays; or a plain 1D array that simulates multidimensional array through index recalculation).
In C++ use std::vector to model arrays unless you have a specific reason for using an array.
Example of a 3x2 vector filled with 0's called "myArray" being initialized:
vector< vector<int> > myArray(3, vector<int>(2,0));
Passing this construct around is trivial, and you don't need to screw around with passing length (because it keeps track):
void myFunction(vector< vector<int> > &myArray) {
for(size_t x = 0;x < myArray.length();++x){
for(size_t y = 0;y < myArray[x].length();++y){
cout << myArray[x][y] << " ";
}
cout << endl;
}
}
Alternatively you can iterate over it with iterators:
void myFunction(vector< vector<int> > &myArray) {
for(vector< vector<int> >::iterator x = myArray.begin();x != myArray.end();++x){
for(vector<int>::iterator y = x->begin();y != x->end();++y){
cout << *y << " ";
}
cout << endl;
}
}
In C++0x you can use the auto keyword to clean up the vector iterator solution:
void myFunction(vector< vector<int> > &myArray) {
for(auto x = myArray.begin();x != myArray.end();++x){
for(auto y = x->begin();y != x->end();++y){
cout << *y << " ";
}
cout << endl;
}
}
And in c++0x for_each becomes viable with lambdas
void myFunction(vector< vector<int> > &myArray) {
for_each(myArray.begin(), myArray.end(), [](const vector<int> &x){
for_each(x->begin(), x->end(), [](int value){
cout << value << " ";
});
cout << endl;
});
}
Or a range based for loop in c++0x:
void myFunction(vector< vector<int> > &myArray) {
for(auto x : myArray){
for(auto y : *x){
cout << *y << " ";
}
cout << endl;
}
}
*I am not near a compiler right now and have not tested these, please feel free to correct my examples.
If you know the size of the array at compile time you can do the following (assuming the size is [x][10]):
MyFunction(int myArray[][10])
If you need to pass in a variable length array (dynamically allocated or possibly just a function which needs to take different sizes of arrays) then you need to deal with pointers.
And as the comments to this answer state:
boost::multiarray may be appropriate since it more efficiently models a multidimensional array. A vector of vectors can have performance implications in critical path code, but in typical cases you will probably not notice an issue.
Pass it as a pointer, and take the dimension(s) as an argument.
void foo(int *array, int width, int height) {
// initialize xPos and yPos
assert(xPos >= 0 && xPos < width);
assert(yPos >= 0 && yPos < height);
int value = array[yPos * width + xPos];
}
This is assuming you have a simple two-dimensional array, like int x[50][50].
There are already a set of answers with the most of the common suggestions: using std::vector, implementing a matrix class, providing the size of the array in the function argument... I am only going to add yet another solution based on native arrays --note that if possible you should use a higher level abstraction.
At any rate:
template <std::size_t rows, std::size_t cols>
void function( int (&array)[rows][cols] )
{
// ...
}
This solution uses a reference to the array (note the & and the set of parenthesis around array) instead of using the pass-by-value syntax. This forces the compiler not to decay the array into a pointer. Then the two sizes (which could have been provided as compile time constants can be defined as template arguments and the compiler will deduct the sizes for you.
NOTE: You mention in the question that the sizes are actually static constants you should be able to use them in the function signature if you provide the value in the class declaration:
struct test {
static const int rows = 25;
static const int cols = 80;
};
void function( int *array[80], int rows ) {
// ...
}
Notice that in the signature I prefer to change the double dimension array for a pointer to an array. The reason is that this is what the compiler interprets either way, and this way it is clear that there is no guarantee that the caller of the function will pass an array of exactly 25 lines (the compiler will not enforce it), and it is thus apparent the need for the second integer argument where the caller passes the number of rows.
You can't pass an arbitrary size like that; the compiler doesn't know how to generate the pointer arithmetic. You could do something like:
MyFunction(int myArray[][N])
or you could do:
MyFunction(int *p, int M, int N)
but you'll have to take the address of the first element when you call it (i.e. MyFunction(&arr[0][0], M, N).
You can get round all of these problems in C++ by using a container class; std::vector would be a good place to start.
The compiler is complaining because it needs to know the size of the all but the first dimension to be able to address an element in the array. For instance, in the following code:
int array[M][N];
// ...
array[i][j] = 0;
To address the element, the compiler generates something like the following:
*(array+(i*N+j)) = 0;
Therefore, you need to re-write your signature like this:
MyFunction(int array[][N])
in which case you will be stuck with a fixed dimension, or go with a more general solution such as a (custom) dynamic 2D array class or a vector<vector<int> >.
Use a vector<vector<int> > (this would be cheating if underlying storage was not guaranteed to be contiguous).
Use a pointer to element-of-array (int*) and a size (M*N) parameter. Here be dragons.
First, lets see why compiler is complaining.
If an array is defined as int arr[ ROWS ][ COLS ]; then any array notation arr[ i ][ j ] can be translated to pointer notation as
*( arr + i * COLS + j )
Observe that the expression requires only COLS, it does not require ROWS. So, the array definition can be written equivalently as
int arr [][ COLS ];
But, missing the second dimension is not acceptable. For little more details, read here.
Now, on your question:
Is there a way to rewrite the
parameter list so that I can pass an
array with any size to the function?
Yes, perhaps you can use a pointer, e.g. MyFunction( int * arr );. But, think about it, how would MyFunction() know where to stop accessing the array? To solve that you would need another parameter for the length of the array, e.g. MyFunction( int * arr, size_t arrSize );
Yes: MyFunction(int **myArray);
Careful, though. You'd better know what you're doing. This will only accept an array of int pointers.
Since you're trying to pass an array of arrays, you'll need a constant expression as one of the dimentions:
MyFunction(int myArray[][COLS]);
You'll need to have COLS at compile time.
I suggest using a vector instead.
Pass a pointer and do the indexing yourself or use a Matrix class instead.
yes - just pass it as pointer(s):
MyFunction(int** someArray)
The downside is that you'll probably need to pas the array's lengths as well
Use MyFunction(int *myArray[])
If you use MyFunction(int **myArray) an pass int someArray[X][Y], the program will crash.
EDIT: Don't use the first line, it's explained in comments.
I don't know about C++, but the C99 standard introduced variable length arrays.
So this would work in a compiler that supports C99:
void func(int rows, int cols, double[rows][cols] matrix) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
printf("%f", matrix[r][c]);
}
}
}
Note that the size arguments come before the array. Really, only the number of columns has to be known at compile time, so this would be valid as well:
void func(int rows, int cols, double[][cols] matrix)
For three or more dimensions, all but the first dimension must have known sizes. The answer ArunSaha linked to explains why.
Honestly, I don't know whether C++ supports variable-length arrays, so this may or may not work. In either case, you may also consider encapsulating your array in some sort of matrix class.
EDIT: From your edit, it looks like C++ may not support this feature. A matrix class is probably the way to go. (Or std::vector if you don't mind that the memory may not be allocated contiguously.)
Don't pass an array, which is an implementation detail. Pass the Board
MyFunction(Board theBoard)
{
...
}
in reality my array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).
That's strange, it works perfectly fine for me:
struct Board
{
static const int ROWS = 6;
static const int COLS = 7;
};
void MyFunction(int myArray[Board::ROWS][Board::COLS])
{
}
Maybe ROWS and COLS are private? Can you show us some code?
In C++, using the inbuilt array types is instant fail. You could use a boost::/std:: array of arrays or vector of arrays. Primitive arrays are not up to any sort of real use
In C++0x, you can use std::initializer_list<...> to accomplish this:
MyFunction(std::initializer_list<std::initializer_list<int>> myArray);
and use it (I presume) like this (with the range based for syntax):
for (const std::initializer_list<int> &subArray: myArray)
{
for (int value: subArray)
{
// fun with value!
}
}

How can I pass a dynamic multidimensional array to a function?

How can I pass a multidimensional array to a function in C/C++ ?
The dimensions of array are not known at compile time
A pointer to the start of the array along with the dimensions - then do the array arithmetic in the function is the most common solution.
Or use boost
Passing the array is easy, the hard part is accessing the array inside your function. As noted by some of the other answers, you can declare the parameter to the function as a pointer and also pass the number of elements for each dim of the array.
#define xsize 20
#define ysize 30
int array[xsize][ysize];
void fun(int* arr, int x, int y)
{
// to access element 5,20
int x = arr[y*5+20];
}
fun(array, xsize, ysize);
Of course, I've left out the whole business of allocating the array (since it isn't known what its size will be, you can't really use #defines (and some say they're bad anyhow)
Use a vector of vectors, you can pass a vector.
You could pass a pointer and sizes, or use a std::vector. But the "real" solution is with a template:
template <size_t N, size_t M>
void foo(int (&pArray)[N][M]);
This function template accepts a N by M array of ints, by reference. Note this is a function template, not a function, so you do get a different instantiated function per array type.
I think this is a GCC extension (or a quite modern C feature), but it can be quite convenient:
void foo(int bar[n][m], int n, int m) {...}
You can pass the pointer to initial memory location of your multi dimension array. you should also pass the size of array i.e. limit of each dimension.
i.e
int var [x][y][z];
func (var, x, y, z);
function definintion:
void func (int*, int, int, int);
I'm just summarizing the options from other posts.
If the number of dimensions (the N as in N-dimensional array) is unknown, the only way is to use a C++ multidimensional array class. There are several publicly available implementations, from Boost or other libraries. See Martin Beckett's post.
If the number of dimensions is known but the array size is dynamic, see Tom's answer for accessing an array element (converting multi index into element pointer). The array itself will have to be allocated with malloc or new.
If you are writing the multidimensional array class yourself, you'll need to know about Row-major-order, Column-major-order, etc.
Namely, if the array dimensios is (Size1, Size2, Size3, ..., SizeN), then:
The number of elements in the array is (Size1 * Size2 * Size3 * ... * SizeN)
The memory needed is sizeof(value_type) * numOfElements
To access the element (index1, index2, index3, ..., indexN), use
ptr[ index1 + (Size1 * index2) + (Size1 * Size2 * index3) + ... ] assuming the first array index is the fastest-moving dimension
Section 3.4 on this page addresses your question:
http://www.programmersheaven.com/2/Pointers-and-Arrays-page-2
Of course variable-length arrays were not present in C until C99 and as far as I know they are not present in C++. Also, MSVC does not implement/support C99.
A simple method is to flatten the array and iterate using dimensions.
#include <stdio.h>
void print_array(int *arr,int row,int col)
{
int i,j;
for(i=0;i<row;i++){
for(j=0;j<col;j++){
printf("%d ",*(arr+i*col+j));
}
printf("\n");
}
}
int main()
{
int a[2][3] = {{1,0,2},{-1,3,1}};
int b[4] = {1,2,3,34};
print_array(a,2,3);
return 0;
}
This technique works but flattening array might prevent compiler optimizations which in turn might result in slow execution.