Why do we specify arrays size as a parameter when passing to function in C++? - c++

I searched this question, most of them says the same thing. Since we only pass the arrays address in a function, compiler can not know the arrays size by looking at the address, they say. I tried to test this by using this code, and both functions gave the same results. So, how does specifying the arrays size as a function parameter help me in a practical way?. In which conditions does specifying the size help us?.
class ArrayTest
{
public:
void say(int ar[])
{
cout<<ar[1]<<endl;
cout<<ar[7]<<endl;
}
void say(int ar[],int sizeAn)
{
cout<<ar[1]<<endl;
cout<<ar[7]<<endl;
}
};
int main()
{
ArrayTest test;
int anAr[5] = {1,2,3,4,5};
test.say(anAr);
test.say(anAr,5);
return 0;
}

This is about you as a programmer having the chance to boundary check, not whether the compiler can do it.
Just try to print out all the elements in the array, with the size:
void say(int ar[],int sizeAn)
{
for(int i=0; i< sizeAn; ++i)
cout<<ar[i]<<endl;
}
now without the size:
void say(int ar[])
{
for(int i=0; i< /*HOW DO I KNOW NOW?*/; ++i)
cout<<ar[i]<<endl;
}

Passing array size as a function parameter is a bad idea, because if you need an array as an array in function passing its size won't have any effect. The array you passed will be decayed to a pointer. So you need to maintain array as is.
Templates provide a simple and effective way to prevent array decay while passing them as function arguments.
template<std::size_t N>
void foo(int (&your_array)[N])
{
for(int i = 0; i < N; i++)
//process array, N will be your array size.
}
//simply pass array when calling the function. N be taken automatically.
//somewhere else
int main()
{
int arr[10];
foo(arr);
}
hope this helps.

Note that your code is invoking undefined behavior because you're accessing element 7 of an array that is only 5 elements big. Using the size parameter, you could for instance check if the index is past its size and not do that call instead.
In your example, you get the same results becaue you aren't actually using the parameter:
void say(int ar[],int sizeAn)
{
cout<<ar[1]<<endl;
cout<<ar[7]<<endl;
}
sizeAn is unused, so it's not making any difference. But consider for instance the following code:
void say(int ar[],int sizeAn)
{
for (int i = 0; i < sizeAn; i++){
cout<<ar[i]<<endl;
}
}
Here, it's printing all the items in the array, so it needs to know how big the array is. If you used an std::vector, for instance, you wouldn't need to pass the size as you can just call the size function, but you can't do that with C style arrays, so you need to pass that size as a parameter if you want to write a function that behaves differently depending on the size).
Or here's a more practical example of your code where the size parameter is used to avoid the undefined behavior:
void say(int ar[],int sizeAn)
{
cout<<ar[1]<<endl;
if (sizeAn >= 8){
cout<<ar[7]<<endl;
}
}
Now it's the same as your code with the change that it's only printing the element 7 if it actually exists.

As you say, compilers can't tell how big an array is if passed to a function. Your first say function tries to reference past the end of the array (ar[7] is beyond the size of 5). Your second say function means you can length check to make sure you don't make this error.
void say(int ar[], int sizeAn)
{
if(sizeAn>1)
cout<<ar[1];endl;
if(sizeAn>7)
cout<<ar[7];endl;
}
This way, YOU know the length and the function can check it before accessing invalid memory locations.

Why do we specify arrays size as a parameter when passing to function in C++?
Do we?
Well, sometimes. The canonical way to pass a range in C++ is using an iterator-pair though, even if I can see it evolve to using ranges when the Range-TS is finally used everywhere.
Anyway, there are other ways to convey what (sub-)range we want to work with. So, let's take a look:
In-band-signalling, like NUL-terminator for c-strings.
An implicit part of the functions contract, like "it will always be exactly 12 elements".
Passing a view of the part we want. Unfortunately, until the ranges-TS is fully incorporated, standard-library-support for that is severely anemic, being restricted to std::string_view in C++17 and extended with std::span for contiguous ranges (like arrays) in C++20 (look at the guideline-support-library for now).
Using an iterator-pair. The full flexibility of iterators, though calculating the length might be costly, or impossible without consuming the range. This is the preferred way in the standard-library.
Using start-iterator and length. Also quite common, but not to the same degree, and does not allow iterators determining the length as you iterate, not that that is an issue here.
Using a (constant where appropriate) reference to the whole container or range, probably templated for generality. This might be combined with point 3, but need not.
Of those, if you know the element-type, and restrict to contiguous arrays, pointer+length is the most comfortable and flexible to use for now, which does not need different code for different lengths, so that's that.

Related

Trying to pass 3d array to function c++ [duplicate]

So I have several questions. First how do I pass a 3D array into a function. I need to pass the whole array as the function is to run a loop to output the contents of the array to a file. This is what I currently have
int array[5][3][3]
void function(int a[5][3][3])
{
//...
}
void function(array); //or void function(array[5][3][3]);
I have found a way to make it work using pointers to the array, however I have asked my teacher and he does not want us to use pointers.
My second question is if I plan to modify a global variable inside a function, I do not need to pass it to the function? I can just use it inside the function as I would inside main?
Yet another problem I am having now is passing a single value from an array into a function.
In a loop I need to pull a value from an array[i][j][2] (i and j being indexes of an outer and inner loop) and pass it to a function to evaluate whether or not it is greater than 90. This is for a school assignment, so understand there are certain specifications I have to meet. (Like not using pointers, and passing a whole array, and passing one value from an array, because as a class we have not yet learned how to use pointers)
Your code is correct, but actually there no such thing as an array parameter in C++ (or in C). Silently the compiler will convert your code to the equivalent pointer type, which is
int array[5][3][3];
void function(int (*a)[3][3])
{
...
}
So although your professor told you not to use pointers, actually you cannot avoid them, because there's really no such thing as an array type parameter in C++.
Second question, the only point of globals is that you can refer to them anywhere, so no need to pass them as parameters.
For passing complex arrays I prefer to wrap them in a structure:
struct array {
int a[5][3][3];
};
void function(struct array *a) ...
This avoids a lot of pitfalls with trying to pass arrays as function arguments.
you might use a pointer instead int ***a
int array[5][3][3]
void dummy(int d[][3][3])
{
d[1][1][1] = 0;
}
you may also pass it as a void * then make
int array[5][3][2]
void function(int* b)
{
int i=0;
int j=1;
int k=2;
l[ k*(3*2)+j*(2)+i ] = 9;
}
function((int*) array);

Can I determine the size/length of an array in C++ without having to hardcode it?

I am basically looking for some sort of "dynamic" way of passing the size/length of an array to a function.
I have tried:
void printArray(int arrayName[])
{
for(int i = 0 ; i < sizeof(arrayName); ++i)
{
cout << arrayName[i] << ' ';
}
}
But I realized it only considers its bytesize and not how many elements are on the array.
And also:
void printArray(int *arrayName)
{
while (*arrayName)
{
cout << *arrayName << ' ';
*arrayName++;
}
}
This has at least printed me everything but more than what I expected, so it doesn't actually work how I want it to.
I reckon it is because I don't exactly tell it how big I need it to be so it plays it "safe" and throws me some big size and eventually starts printing me very odd integers after my last element in the array.
So I finally got this work around, yet I believe there is something better out there!:
void printArray(int *arrayName)
{
while (*arrayName)
{
if (*arrayName == -858993460)
{
break;
}
cout << *arrayName << ' ';
*arrayName++;
}
cout << '\n';
}
After running the program a few times I realized the value after the last element of the array that I have input is always: -858993460, so I made it break the while loop once this value is encountered.
include <iostream>
include <conio.h>
using namespace std;
// functions prototypes
void printArray (int arrayName[], int lengthArray);
// global variables
//main
int main ()
{
int firstArray[] = {5, 10, 15};
int secondArray[] = {2, 4, 6, 8, 10};
printArray (firstArray,3);
printArray (secondArray,5);
// end of program
_getch();
return 0;
}
// functions definitions
void printArray(int arrayName[], int lengthArray)
{
for (int i=0; i<lengthArray; i++)
{
cout << arrayName[i] << " ";
}
cout << "\n";
}
Thank you very much.
TL;DR answer: use std::vector.
But I realized it [sizeof()] only considers its bytesize and not how many elements are on the array.
That wouldn't be a problem in itself: you could still get the size of the array using sizeof(array) / sizeof(array[0]), but the problem is that when passed to a function, arrays decay into a pointer to their first element, so all you can get is sizeof(T *) (T being the type of an element in the array).
About *arrayName++:
This has at least printed me everything but more than what I expected
I don't even understand what inspired you to calculate the size of the array in this way. All that this code does is incrementing the first object in the array until it's zero.
After running the program a few times I realized the value after the last element of the array that I have input is always: -858993460
That's a terrible assumption and it also relies on undefined behavior. You can't really be sure what's in the memory after the first element of your array, you should not even be accessing it.
Basically, in C++, if you want to know the size of a raw array from within a function, then you have to keep track of it manually (e. g. adding an extra size_t size argument), because of the way arrays are passed to functions (remember, they "decay into" a pointer). If you want something more flexible, consider using std::vector<int> (or whatever type of objects you want to store) from the C++ standard library -- it has a size() method, which does exactly what you want.
1st try
When arrays are passed into functions they decay to pointers. Normally, using sizeof on an array would give you its size in bytes which you could then divide by the size in bytes of each element and get the number of elements. But now, since you have a pointer instead of an array, calling sizeof just gives you the size of the pointer (usually 4 or 8 bytes), not the array itself and that's why this fails.
2nd try
The while loop in this example assumes that your array ends with a zero and that's very bad (unless you really did use a zero as a terminator like null-terminated strings for example do). If your array doesn't end with a zero you might be accessing memory that isn't yours and therefore invoking undefined behavior. Another thing that could happen is that your array has a zero element in the middle which would then only print the first few elements.
3rd try
This special value you found lurking at the end of your array can change any time. This value just happened to be there at this point and it might be different another time so hardcoding it like this is very dangerous because again, you could end up accessing memory that isn't yours.
Your final code
This code is correct and passing the length of the array along with the array itself is something commonly done (especially in APIs written in C). This code shouldn't cause any problems as long as you don't pass a length that's actually bigger than the real length of the array and this can happen sometimes so it is also error prone.
Another solution
Another solution would be to use std::vector, a container which along with keeping track of its size, also allows you to add as many elements as you want, i.e. the size doesn't need to be known at runtime. So you could do something like this:
#include <iostream>
#include <vector>
#include <cstddef>
void print_vec(const std::vector<int>& v)
{
std::size_t len = v.size();
for (std::size_t i = 0; i < len; ++i)
{
std::cout << v[i] << std::endl;
}
}
int main()
{
std::vector<int> elements;
elements.push_back(5);
elements.push_back(4);
elements.push_back(3);
elements.push_back(2);
elements.push_back(1);
print_vec(elements);
return 0;
}
Useful links worth checking out
Undefined behavior: Undefined, unspecified and implementation-defined behavior
Array decay: What is array decaying?
std::vector: http://en.cppreference.com/w/cpp/container/vector
As all the other answers say, you should use std::vector or, as you already did, pass the number of elements of the array to the printing function.
Another way to do is is by putting a sentinel element (a value you are sure it won't be inside the array) at the end of the array. In the printing function you then cycle through the elements and when you find the sentinel you stop.
A possible solution: you can use a template to deduce the array length:
template <typename T, int N>
int array_length(T (&array)[N]) {
return N;
}
Note that you have to do this before the array decays to a pointer, but you can use the technique directly or in a wrapper.
For example, if you don't mind rolling your own array wrapper:
template <typename T>
struct array {
T *a_;
int n_;
template <int N> array(T (&a)[N]) : a_(a), n_(N) {}
};
You can do this:
void printArray(array<int> a)
{
for (int i = 0 ; i < a.n_; ++i)
cout << a.a_[i] << ' ';
}
and call it like
int firstArray[] = {5, 10, 15};
int secondArray[] = {2, 4, 6, 8, 10};
printArray (firstArray);
printArray (secondArray);
The key is that the templated constructor isn't explicit so your array can be converted to an instance, capturing the size, before decaying to a pointer.
NB. The wrapper shown isn't suitable for owning dynamically-sized arrays, only for handling statically-sized arrays conveniently. It's also missing various operators and a default constructor, for brevity. In general, prefer std::vector or std::array instead for general use.
... OP's own attempts are completely addressed elsewhere ...
Using the -858993460 value is highly unreliable and, in fact, incorrect.
You can pass a length of array in two ways: pass an additional parameter (say size_t length) to your function, or put a special value to the end of array. The first way is preferred, but the second is used, for example, for passing strings by char*.
In C/C++ it's not possible to know the size of an array at runtime. You might consider using an std::vector class if you need that, and it has other advantages as well.
When you pass the length of the array to printArray, you can use sizeof(array) / sizeof(array[0]), which is to say the size in bytes of the whole array divided by the size in bytes of a single element gives you the size in elements of the array itself.
More to the point, in C++ you may find it to your advantage to learn about std::vector and std::array and prefer these over raw arrays—unless of course you’re doing a homework assignment that requires you to learn about raw arrays. The size() member function will give you the number of elements in a vector.
In C/C++, native arrays degrade to pointers as soon as they are passed to functions. As such, the "length" parameter has to be passed as a parameter for the function.
C++ offers the std::vector collection class. Make sure when you pass it to a function, you pass it by reference or by pointer (to avoid making a copy of the array as it's passed).
#include <vector>
#include <string>
void printArray(std::vector<std::string> &arrayName)
{
size_t length = arrayName.size();
for(size_t i = 0 ; i < length; ++i)
{
cout << arrayName[i] << ' ';
}
}
int main()
{
std::vector<std::string> arrayOfNames;
arrayOfNames.push_back(std::string("Stack"));
arrayOfNames.push_back(std::string("Overflow"));
printArray(arrayOfNames);
...
}

Arrays and length in C++

I'm trying to get the length of an array passed as a parameter on some function.
The code is look like this :
double getAverage(int numbers[])
{
int length = sizeof(numbers)/sizeof(numbers[0]);
// here the result of the length is 1.
int sum = 0;
for (int i = 0 ; i < length ; i++)
{
sum += numbers[i];
}
return (double)sum / length;
}
int main()
{
int numbers[8] = {1,2,3,4,5,6,7,8};
//if I call here sizeof(numbers)/sizeof(numbers[0] the result will be 8 as it
//should be.
cout << getAverage(numbers) << endl;
return 0;
}
My question is how to get the array length which is passed as argument of a function by reference(although I know that every array is passed by reference)?
I know that there is a lot of questions about finding the array length in C/C++ but no one of them give me the answer which I'm looking for.
Thanks in advance.
You will have to explicitly pass the length of the array as an parameter to the function.
What you pass to the function is just an pointer to the array, not the array itself, so there is no way to determine the length of the array inside the function unless you explicitly pass the length as an function parameter.
You can probably use std::vector, which provides member functions to get no of elements in the vector, using std::vector::size(), that is the best you can do there is no way to do so using c-style arrays.
Arrays decay to pointers when passing them as parameters. You can't retrieve size information inside the function.
Why aren't you using std::vector? It's the c++ way.
At run-time, there is no information associated with an array that tells you its length. The array pretty much "decays" into just the address of the first element.
At compile-time, the length is part of the type, so if you declare your function to take e.g. int numbers[8] you can get the length using the sizeof expression you mention.
Of course, this means you can only validly call the function with arrays of length 8, which kind of makes it a bit useless.
Thus, the only way around this is to explicitly add information at run-time about the array's length, by adding a second size_t length argument to the function.
In C++, you could also use templates to have the compiler create specialized versions of the function for each array length, but that is kind of wasteful.
As pointed out by others, you can also "level up" your abstraction and use e.g. std::vector<int> to get a size() method. That is of course pretty much the same thing, the vector container adds run-time information about the number of elements.
This might not be "the answer which you're looking for", I'm sorry about that.
If you must use an array, you could 'templatize' your function:
template <size_t length> double getAverage(int (&numbers)[length]) {
int sum = 0;
for (int i = 0 ; i < length ; i++)
{
sum += numbers[i];
}
return (double)sum / length;
}
You have to pass in the length as a parameter, or use std::vector which "contains" the length. You can access it with the size() method.
Or use std::vector (instead of int[]) which provides a size() function
You can use std::vector, or std::list as all have give. But if you are adamant that you want to use an int[] without a second argument, then you can insert a code number as the last element of the array. that way you can know the end.... Or u can save the length of the array in its first element and use the rest normally.
You can pass an array by reference in which case the areay size has to be specified. However, the size of a statically sized array can be deduced for a template argument:
template <int Size>
double getAverage(int (&numbers)[Size]) { ... }
The only problem with this approach is that it creates a new instantiation for each array size. Of course, the fix to this is to actually pass begin and end iterators to the function doing the actual work. The iterators can easily be determined using begin() and end() functions using the trick above. The code would look something like this:
double average
= std::accumulate(begin(numbers), end(numbers), 0.0)
/ std::distance(begin(numbers), end(numbers));
You can use templates:
template<std::size_t Length>
double getAverage(int (&numbers)[Length])
{
...
}
but this may lead to code bloat as the compiler will create this for every new array size you pass in. You might be better off combining a template with a parameter
template<typename T, std::size_t Length>
std::size_t GetCount(T (&numbers)[Length])
{
return Length;
}
[main]
getAverage(numbers, GetCount(numbers));

Handling multi-dimensional array lengths in C++

I would like to build a function that takes a multidimensional array and prints it like a grid. I'm having trouble with it because c++ doesn't allow a function to have a multidimensional array argument unless you specify its length. There is a question about it on here, that was answered using vectors. I haven't learned how to use vectors yet, so please don't use them in an answer, or at least provide a good tutorial on them if you do.
Anyway, I was wondering if it's possible to return an array in c++... I started programming with javascript, so the first solution I thought of was to do something like
int gen(int len){
return int arr(int a[][len]){
cout << a[0][0];
};
}
I knew it wouldn't work, tried it, and wasn't surprised when it didn't. Is there a way to do something like this though?
In C++ you can pass array by reference. With making an array a template, it's possible to receive any length in the function. For example,
template<size_t SIZE1>
void print (int (&arr)[SIZE1])
{ ... }
template<size_t SIZE1, size_t SIZE2>
void print (int (&arr)[SIZE1][SIZE2])
{ ... }
template<size_t SIZE1, size_t SIZE2, size_t SIZE3>
void print (int (&arr)[SIZE1][SIZE2][SIZE3])
{ ... }
This pattern will internally create a unique function for every different size of array. It offers ease of use, but may increase the code size.
You have to know the size of the array, there's no way around it. std::vector is the correct way to solve this, and you can find a good reference here. That allows passing only the vector, as it knows its own length and the function can ask it, making it similar to what you're used to from Javascript.
Otherwise, you must pass the size of the array to the function one way or another.
One way is using templates, but that would not work on dynamic arrays (and is a bit wasteful, as it creates a copy of the function per each array size used). The other is just adding an additional parameter to the function, with the size.

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