Passing a 2D array to a C++ function

passing 2d array to function in c using pointers
passing 2d array to function in c++
pass 2d array to function c++ example
passing 3d array to function in c
passing 2d dynamic array to function - c++
pass 2d array to function c++ without size
passing array to function in c by reference
2d array in c

I have a function which I want to take, as a parameter, a 2D array of variable size.

So far I have this:

void myFunction(double** myArray){
     myArray[x][y] = 5;
     etc...
}

And I have declared an array elsewhere in my code:

double anArray[10][10];

However, calling myFunction(anArray) gives me an error.

I do not want to copy the array when I pass it in. Any changes made in myFunction should alter the state of anArray. If I understand correctly, I only want to pass in as an argument a pointer to a 2D array. The function needs to accept arrays of different sizes also. So for example, [10][10] and [5][5]. How can I do this?

There are three ways to pass a 2D array to a function:

  1. The parameter is a 2D array

    int array[10][10];
    void passFunc(int a[][10])
    {
        // ...
    }
    passFunc(array);
    
  2. The parameter is an array containing pointers

    int *array[10];
    for(int i = 0; i < 10; i++)
        array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
        // ...
    }
    passFunc(array);
    
  3. The parameter is a pointer to a pointer

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
        array[i] = new int[10];
    void passFunc(int **a)
    {
        // ...
    }
    passFunc(array);
    

How to pass a 2D array as a parameter in C?, C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way  How to pass Two Dimensional Array in a function in C | in Hindi Program to Pass two D array in a Function Program to Pass Two d Array in a function using macros C tutorials in Hindi C Tutorials

Fixed Size

1. Pass by reference

template <size_t rows, size_t cols>
void process_2d_array_template(int (&array)[rows][cols])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

In C++ passing the array by reference without losing the dimension information is probably the safest, since one needn't worry about the caller passing an incorrect dimension (compiler flags when mismatching). However, this isn't possible with dynamic (freestore) arrays; it works for automatic (usually stack-living) arrays only i.e. the dimensionality should be known at compile time.

2. Pass by pointer

void process_2d_array_pointer(int (*array)[5][10])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << (*array)[i][j] << '\t';
        std::cout << std::endl;
    }    
}

The C equivalent of the previous method is passing the array by pointer. This should not be confused with passing by the array's decayed pointer type (3), which is the common, popular method, albeit less safe than this one but more flexible. Like (1), use this method when all the dimensions of the array is fixed and known at compile-time. Note that when calling the function the array's address should be passed process_2d_array_pointer(&a) and not the address of the first element by decay process_2d_array_pointer(a).

Variable Size

These are inherited from C but are less safe, the compiler has no way of checking, guaranteeing that the caller is passing the required dimensions. The function only banks on what the caller passes in as the dimension(s). These are more flexible than the above ones since arrays of different lengths can be passed to them invariably.

It is to be remembered that there's no such thing as passing an array directly to a function in C [while in C++ they can be passed as a reference (1)]; (2) is passing a pointer to the array and not the array itself. Always passing an array as-is becomes a pointer-copy operation which is facilitated by array's nature of decaying into a pointer.

3. Pass by (value) a pointer to the decayed type

// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Although int array[][10] is allowed, I'd not recommend it over the above syntax since the above syntax makes it clear that the identifier array is a single pointer to an array of 10 integers, while this syntax looks like it's a 2D array but is the same pointer to an array of 10 integers. Here we know the number of elements in a single row (i.e. the column size, 10 here) but the number of rows is unknown and hence to be passed as an argument. In this case there's some safety since the compiler can flag when a pointer to an array with second dimension not equal to 10 is passed. The first dimension is the varying part and can be omitted. See here for the rationale on why only the first dimension is allowed to be omitted.

4. Pass by pointer to a pointer

// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Again there's an alternative syntax of int *array[10] which is the same as int **array. In this syntax the [10] is ignored as it decays into a pointer thereby becoming int **array. Perhaps it is just a cue to the caller that the passed array should have at least 10 columns, even then row count is required. In any case the compiler doesn't flag for any length/size violations (it only checks if the type passed is a pointer to pointer), hence requiring both row and column counts as parameter makes sense here.

Note: (4) is the least safest option since it hardly has any type check and the most inconvenient. One cannot legitimately pass a 2D array to this function; C-FAQ condemns the usual workaround of doing int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10); as it may potentially lead to undefined behaviour due to array flattening. The right way of passing an array in this method brings us to the inconvenient part i.e. we need an additional (surrogate) array of pointers with each of its element pointing to the respective row of the actual, to-be-passed array; this surrogate is then passed to the function (see below); all this for getting the same job done as the above methods which are more safer, cleaner and perhaps faster.

Here's a driver program to test the above functions:

#include <iostream>

// copy above functions here

int main()
{
    int a[5][10] = { { } };
    process_2d_array_template(a);
    process_2d_array_pointer(&a);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(a, 5);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[10]

    int *b[5];  // surrogate
    for (size_t i = 0; i < 5; ++i)
    {
        b[i] = a[i];
    }
    // another popular way to define b: here the 2D arrays dims may be non-const, runtime var
    // int **b = new int*[5];
    // for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
    process_pointer_2_pointer(b, 5, 10);
    // process_2d_array(b, 5);
    // doesn't work since b's first dimension decays into a pointer thereby becoming int**
}

How to pass 2D array (matrix) in a function in C?, To pass multidimensional arrays to a function, only the name of the array is passed to the function(similar to  Passing a pointer to a char array as an argument to a function - C In the following function declaration, the first argument is a String, specifically, an array of chars, and the third argument is a pointer to an integer.

A modification to shengy's first suggestion, you can use templates to make the function accept a multi-dimensional array variable (instead of storing an array of pointers that have to be managed and deleted):

template <size_t size_x, size_t size_y>
void func(double (&arr)[size_x][size_y])
{
    printf("%p\n", &arr);
}

int main()
{
    double a1[10][10];
    double a2[5][5];

    printf("%p\n%p\n\n", &a1, &a2);
    func(a1);
    func(a2);

    return 0;
}

The print statements are there to show that the arrays are getting passed by reference (by displaying the variables' addresses)

Pass arrays to a function in C, In this post, we will see how we can pass 2D array to a function in C programming language. 1. For Static Array. If we know the array bounds at compile time, we  C++ Passing Arrays to Functions - C++ does not allow to pass an entire array as an argument to a function. However, You can pass a pointer to an array by specifying the array's name without an i

You can create a function template like this:

template<int R, int C>
void myFunction(double (&myArray)[R][C])
{
    myArray[x][y] = 5;
    etc...
}

Then you have both dimension sizes via R and C. A different function will be created for each array size, so if your function is large and you call it with a variety of different array sizes, this may be costly. You could use it as a wrapper over a function like this though:

void myFunction(double * arr, int R, int C)
{
    arr[x * C + y] = 5;
    etc...
}

It treats the array as one dimensional, and uses arithmetic to figure out the offsets of the indexes. In this case, you would define the template like this:

template<int C, int R>
void myFunction(double (&myArray)[R][C])
{
    myFunction(*myArray, R, C);
}

How to Pass 2D Array to a Function as a Parameter in C, A one dimensional array can be easily passed as a pointer, but syntax for passing a 2D array to a function can be difficult to remember. One important thing for  How to pass a 2D array as a parameter in C? This post is an extension of How to dynamically allocate a 2D array in C? A one dimensional array can be easily passed as a pointer, but syntax for passing a 2D array to a function can be difficult to remember.

Surprised that no one mentioned this yet, but you can simply template on anything 2D supporting [][] semantics.

template <typename TwoD>
void myFunction(TwoD& myArray){
     myArray[x][y] = 5;
     etc...
}

// call with
double anArray[10][10];
myFunction(anArray);

It works with any 2D "array-like" datastructure, such as std::vector<std::vector<T>>, or a user defined type to maximize code reuse.

C Programming, We have learned that in chapter Two Dimensional Array in C that when a 2-D is passed to a function it is optional to specify the size of the left most dimensions. Passing Arrays as Function Arguments in C - If you want to pass a single-dimension array as an argument in a function, you would have to declare a formal parameter in one of following three ways and all t

How to pass a 2D array as a parameter in C, Here, we have a C program, in which we are demonstrating an example of passing two dimensional arrays to a function. Pass arrays to a function in C In this tutorial, you'll learn to pass arrays (both one-dimensional and multidimensional arrays) to a function in C programming with the help of examples. In C programming, you can pass en entire array to functions.

Passing 2-D Array to a Function in C, Passing Array to a Function in C++ Programming In this article, you'll learn to pass an array to a function in C++. You'll learn to pass both one-dimensional and multi-dimensional arrays.

Passing 2d-array to function, C Programming - Passing a multi-dimensional array to a function Posted on March 27, 2019 by Paul . In this article I will show you how to pass a multi-dimensional array as a parameter to a function in C. For simplicity, we will present only the case of 2D arrays, but same considerations will apply to a general, multi-dimensional, array.

Comments
  • cannot convert parameter 3 from 'double [10][10]' to 'double **'
  • The accepted answer shows only 2 techniques [its (2) and (3) are the same] but there're 4 unique ways of passing a 2D array to a function.
  • Strictly speaking, yes, they aren't 2D arrays, but this convention (albeit leading to UB) of having an array of pointers, each pointing to (a 1D) array, seems to be prevalent :( Having a flattened 1D array of m x n length, with helper functions/class to emulate a 2D array is perhaps better.
  • EASIEST- func(int* mat, int r, int c){ for(int i=0; i<r; i++) for(int j=0; j<c; j++) printf("%d ", *(mat+i*c+j)); }. Call it like- int mat[3][5]; func(mat[0], 3, 5);
  • @Overflowh You can get the elements of array with array[i][j] :)
  • For the 1st case, the parameter can be declared as int (*a)[10].
  • For the 2nd case, the parameter can be declared as int **.
  • @Zack: You're right, there're only really two cases; one is a pointer-to-pointer and other being a single pointer to an integer array of size n i.e. int (*a) [10].
  • Case 2 and 3 aren't 2D arrays, so this answer is misleading. See this.
  • What about passing dynamically allocated arrays to functions in C++? In C11 standard it can be done for statically and dynamically allocated arrays like that fn(int col,int row, int array[col][row]): stackoverflow.com/questions/16004668/… I have made the question for this problem: stackoverflow.com/questions/27457076/…
  • @42n4 Case 4 covers (for C++ as well) that. For dynamically allocated arrays, just the line inside the loop would change from b[i] = a[i]; to, say, b[i] = new int[10];. One may also make b dynamically allocated int **b = int *[5]; and it'll still work as-is.
  • How does addressing array[i][j] work into the function in 4)? Because it has received ptr to ptr and does not know the value of last dimension, which is necessary to perform a shift for correct addressing?