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.
Related
I have encountered a problem with passing two dimensional arrays to other function as parameter.
It was not working when I tried as below.
#include <stdio.h>
int display(int **src) {
printf("%d", src[0][1]);
}
int main() {
int arr[2][2] = {{1,2}, {3,4}};
display(arr);
return 0;
}`
It raises segmentation fault error. So I changed the display function as below
int display(int src[][3]) {
printf("%d", src[0][1]);
}
I am not sure why first case raises error.
Please help me to understand deeply about this case.
int display(int **src) {
printf("%d", src[0][1]);
}
you can not do that because the compiler doesn't know the dimensions (rows and columns), in other words: C doesn't use introspection.
Instead:
int display(int src[][2]) {
printf("%d", src[0][1]);
}
or if you prefer
int display(int (*src)[2]) {
printf("%d", src[0][1]);
}
Note that you don't need to specify the first dimension, C is able to calculate the position based on the offset: (sizeof(int) * cols)
Also, you promised to return something from the function, if you don't want to return a value use:
void display(int (*src)[2]) {
Finally, as pointed out by #Scheff in comments, your original array haves 2 columns, receiving 3 will break the indexing in the receiver.
Pointers are not arrays and arrays are not pointers. There is a common misunderstanding that type** somehow has something to do with 2D arrays. It has not. It is not a 2D array and it cannot point at a 2D array.
There's a look-up table design pattern where you use int** to point at an array of int* items, where each int* points at a chunk of dynamically allocated memory. By using int** we can "emulate" the [x][y] array syntax, so these look-up tables look like 2D arrays, but they are not, because the data is not allocated adjacently. More on that topic here: Correctly allocating multi-dimensional arrays.
The correct way to pass a 2D array to a function is:
void display(int src[2][2]) {
printf("%d", src[0][1]);
}
This does not pass the array by value, as one might think. Just like a regular 1D array, the parameter implicitly "decays" into a pointer to the first element, and the first element of a 2D array is a 1D array. So this is 100% equivalent to void display(int (*src)[2]);. And if we modify src[i][j] from inside the function, we therefore modify the original array allocated by the caller.
And because of this array decay, it actually doesn't matter what size we type for the outer-most (left) dimension. We can as well type void display(int src[][2]); (which is actually an array of imcomplete type) and the result will be the same: a decay into an array pointer int (*)[2].
If standard C variable-length arrays are available, then you can also declare the function with variable dimensions:
void display (size_t x, size_t y, int src[x][y]);
This question already has answers here:
How do I find the length of an array?
(30 answers)
Closed 6 years ago.
I'm writing some code in C++ to do the quick sort algorithm to sort an array of integers. I have my complete code here:
void swap(int A[], int x, int y)
{
int tmp;
tmp=A[x];
A[x]=A[y];
A[y]=tmp;
}
int partition(int A[], int start, int stop)
{
int big=start;
int pivot=A[stop];
for(int i=start; i<stop; i++)
{
if(A[i]<=pivot)
{
swap(A, i, big);
big++;
}
}
swap(A, big, stop);
return big;
}
void quick_Sort_Helper(int A[], int start, int stop)
{
//base cases
if(stop<=start)
{return;}
if(start+1==stop)
{
if(A[start]>A[stop])
{swap(A, start, stop);}
return;
}
//recursive cases
int pivot=partition(A,start, stop);
quick_Sort_Helper(A,start, pivot-1);
quick_Sort_Helper(A, pivot, stop);
}
void quick_Sort(int A[])
{
quick_Sort_Helper(A,0, A.size()-1);
}
I get an error when compiling the program on the line where I call A.size(). The error reads as follows:
error: request for member ‘size’ in ‘A’, which is of non-class type ‘int*’
I don't understand because the size() function of an array is supposed to return an integer with the length/ number of elements in the array.
Raw arrays are pretty dumb. They are a blocks of memory without any support methods. Further, when you pass them around they tend to decay to pointers losing what little meta information they did have. If you need to preserve this information consider using std::vector (resizable) or std::array (static size).
If these are not available for whatever reason, consider writing a simple wrapping structure to contain the sizing information with the array and pass the structure around.
Arrays do not have methods. So this expression A.size()-1 is invalid. You have to pass explicitly to the function the number of elements in the array. Thus the function declaration will look like
void quick_Sort( int A[], size_t n );
where n is the number of elements in the array A.
Array in C++, unlike Java, is not a class. If you want to use Arrays as a class, you could use array class.
array<int,5> A;
Reference to Array class C++
You can't directly pass array into a function in c++, because arrays are second class citizens and they decay into a pointer. If you still want to pass an array, there is no option but to pass the size as a parameter.
If you declared an array in the same scope as asking for it's size, you can do this,
int l = sizeof(A)/sizeof(A[0]);
In C++, an array does not come with any functionality whatsoever; it is quite literally a block of contiguous memory just large enough to hold whatever data it is declared to hold (in your case it is sizeof(int) * numberOfItems).
I suggest moving to use std::vector instead (in your case this would be std::vector< int >), which under the hood does manage an array, but provides the niceties of size() function, iterators, random access, automatic resizing, etc.
Alternatively, if you are going to use arrays directly like this, you need to pass along its length to any function that is going to operate on the array. Otherwise, the function has absolutely no way of knowing the size of the array.
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++)
Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?
I can thing of only one case: the array contains elements that are of different derived types of the type of the array.
Am I right and are there (I am almost positive there must be) other such cases?
Sorry for the trivial question, I am a Java dev and I am rather new to C++.
Thanks!
Let's say I have an array arr. When
would the following not give the
number of elements of the array:
sizeof(arr) / sizeof(arr[0])?
One thing I've often seen new programmers doing this:
void f(Sample *arr)
{
int count = sizeof(arr)/sizeof(arr[0]); //what would be count? 10?
}
Sample arr[10];
f(arr);
So new programmers think the value of count will be 10. But that's wrong.
Even this is wrong:
void g(Sample arr[]) //even more deceptive form!
{
int count = sizeof(arr)/sizeof(arr[0]); //count would not be 10
}
It's all because once you pass an array to any of these functions, it becomes pointer type, and so sizeof(arr) would give the size of pointer, not array!
EDIT:
The following is an elegant way you can pass an array to a function, without letting it to decay into pointer type:
template<size_t N>
void h(Sample (&arr)[N])
{
size_t count = N; //N is 10, so would be count!
//you can even do this now:
//size_t count = sizeof(arr)/sizeof(arr[0]); it'll return 10!
}
Sample arr[10];
h(arr); //pass : same as before!
Arrays in C++ are very different from those in Java in that they are completely unmanaged. The compiler or run-time have no idea whatsoever what size the array is.
The information is only known at compile-time if the size is defined in the declaration:
char array[256];
In this case, sizeof(array) gives you the proper size.
If you use a pointer as an array however, the "array" will just be a pointer, and sizeof will not give you any information about the actual size of the array.
STL offers a lot of templates that allow you to have arrays, some of them with size information, some of them with variable sizes, and most of them with good accessors and bounds checking.
There are no cases where, given an array arr, that the value of sizeof(arr) / sizeof(arr[0]) is not the count of elements, by the definition of array and sizeof.
In fact, it's even directly mentioned (§5.3.3/2):
.... When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element.
Emphasis mine. Divide by the size of an element, sizeof(arr[0]), to obtain n.
Since C++17 you can also use the standardized free function:
std::size(container) which will return the amount of elements in that container.
example:
std::vector<int> vec = { 1, 2, 3, 4, 8 };
std::cout << std::size(vec) << "\n\n"; // 5
int A[] = {40,10,20};
std::cout << std::size(A) << '\n'; // 3
No that would still produce the right value because you must define the array to be either all elements of a single type or pointers to a type. In either case the array size is known at compile time so sizeof(arr) / sizeof(arr[0]) always returns the element count.
Here is an example of how to use this correctly:
int nonDynamicArray[ 4 ];
#define nonDynamicArrayElementCount ( sizeof(nonDynamicArray) / sizeof(nonDynamicArray[ 0 ]) )
I'll go one further here to show when to use this properly. You won't use it very often. It is primarily useful when you want to define an array specifically so you can add elements to it without changing a lot of code later. It is a construct that is primarily useful for maintenance. The canonical example (when I think about it anyway ;-) is building a table of commands for some program that you intend to add more commands to later. In this example to maintain/improve your program all you need to do is add another command to the array and then add the command handler:
char *commands[] = { // <--- note intentional lack of explicit array size
"open",
"close",
"abort",
"crash"
};
#define kCommandsCount ( sizeof(commands) / sizeof(commands[ 0 ]) )
void processCommand( char *command ) {
int i;
for ( i = 0; i < kCommandsCount; ++i ) {
// if command == commands[ i ] do something (be sure to compare full string)
}
}
_countof(my_array) in MSVC
I can thing of only one case: the array contains elements that are of different derived types of the type of the array.
Elements of an array in C++ are objects, not pointers, so you cannot have derived type object as an element.
And like mentioned above, sizeof(my_array) (like _countof() as well) will work just in the scope of array definition.
It seems that if you know the type of elements in the array you can also use that to your advantage with sizeof.
int numList[] = { 0, 1, 2, 3, 4 };
cout << sizeof(numList) / sizeof(int);
// => 5
First off, you can circumvent that problem by using std::vector instead of an array. Second, if you put objects of a derived class into an array of a super class, you will experience slicing, but the good news is, your formula will work. Polymorphic collections in C++ are achieved using pointers. There are three major options here:
normal pointers
a collection of boost::shared_ptr
a Boost.Pointer Container
Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?
In contexts where arr is not actually the array (but instead a pointer to the initial element). Other answers explain how this happens.
I can thing of only one case: the array contains elements that are of different derived types of the type of the array.
This cannot happen (for, fundamentally, the same reason that Java arrays don't play nicely with generics). The array is statically typed; it reserves "slots" of memory that are sized for a specific type (the base type).
Sorry for the trivial question, I am a Java dev and I am rather new to C++.
C++ arrays are not first-class objects. You can use boost::array to make them behave more like Java arrays, but keep in mind that you will still have value semantics rather than reference semantics, just like with everything else. (In particular, this means that you cannot really declare a variable of type analogous to Foo[] in Java, nor replace an array with another one of a different size; the array size is a part of the type.) Use .size() with this class where you would use .length in Java. (It also supplies iterators that provide the usual interface for C++ iterators.)
Use the Microsoft "_countof(array)" Macro. This link to the Microsoft Developer Network explains it and offers an example that demonstrates the difference between "sizeof(array)" and the "_countof(array)" macro.
Microsoft and the "_countof(array)" Macro
If you can not use C++17, which allows to use std::size(container), you can easily implement your own generic sizeofArray template function as a one-liner:
#include <cstddef>
#include <cstdio>
template< typename T, std::size_t N >
inline constexpr std::size_t sizeofArray( const T(&)[N] ) noexcept { return N; }
int x[10];
void* y[100];
long z[1000];
struct {int x; char y; long z;} s[123];
static_assert( sizeofArray(x) == 10, "error" );
static_assert( sizeofArray(y) == 100, "error" );
static_assert( sizeofArray(z) == 1000, "error" );
static_assert( sizeofArray(s) == 123, "error" );
int main() {
puts( "ok" );
}
test it here: http://cpp.sh/8tio3
It will work if and only if arr is a C-Array (type[size]; except for function parameters!), a reference to a C-Array (type(&)[size]) or a pointer to a C-Array (type(*)[size]).
Note you should use std::size or std::ssize instead with current C++-Standards!
In C++17 you can use std::size:
int arr[] = {1, 2, 3};
auto count = std::size(arr); // type std::size_t, value == 3
In C++20 you can additionally get a signed value by using std::ssize:
int arr[] = {1, 2, 3};
auto count = std::ssize(arr); // type std::ptrdiff_t, value == 3
https://en.cppreference.com/w/cpp/iterator/size
Also note that C++ unfortunately inherited from C that C-Arrays are never passed by value (deep copy) to functions.
void f(int a[3]);
is the same as
void f(int* a);
so you loose the information that a is an array and with this, how much elements it had. The 3 is completely ignored by the compiler!
If you want to preserve the datatype (including the array element count), you can use a pointer or a reference to an C-Array:
void f(int (&a)[3]); // reference to C-Array with 3 elements
void f(int (*a)[3]); // pointer to C-Array with 3 elements
void f(int a[3]); // pointer to int
void f(int* a); // pointer to int
If you want to call functions with Arrays call-by-value, you can use C++-Arrays (std::array) from the C++ standard library:
f(std::array<int, 3> a);
std::array<int, 3> arr = {1, 2, 3};
f(arr); // deep copy
https://en.cppreference.com/w/cpp/container/array
Determine how many numbers are in your array.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n[10] ;
int l = sizeof(n)/sizeof(n[0]);
cout << l;
return 0;
}
I know is old topic but what about simple solution like while loop?
int function count(array[]) {
int i = 0;
while(array[i] != NULL) {
i++;
}
return i;
}
I know that is slower than sizeof() but this is another example of array count.
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!
}
}