Passing arrays to functions without using pointers

passing 2d array to function c++
passing array to function in c++
passing array to function in c using pointer
c++ passing array by reference
passing array by reference c++ example
passing 2d array to function in c
how to pass array to function in java
passing 2d array to function in c using pointers

C allows passing arrays to functions using the array name directly. Since the array name is the starting address of the array (address of element [0]) - this is passing by reference - hence even local array can be passed this way - and the changes of either function will be visible to the other without any need of explicit return. What I understand so far is -

  1. The function call just needs to include the name of the array which provides the starting address - and the integer size of each dimension as separate int arguments - this way any function other than the function that contains array definition - has all the information of arrays location and size (array size as well as size of each dimension) and can operate on any element. Once again, since this is pass by reference, any such change will be visible to all such functions including and from the one containing array definition (it will need to pass the same information as arguments to each function - the array name for starting address and each dimension size) , without any return required specifically for these changes to be visible to all functions including the calling function.

  2. The array argument in the function prototype and function definition specifies the array with a pair of square braces for each dimension + in the same argument - the largest ? value for each dimension except the most significant one (rows in a 2-D array) is also specified eg -

    //Prototype  
    return_type function_name ( array_name[][MAX_COLS], int rows, int cols);
    
    // Function call somewhere  
    function_name (array_name, num_rows, num_columns); /* array name refers 
    to starting address */
    

Also for the dimensions for which the largest ? value is specified in prototype and definition (MAX_COLS for our example), the actual value during call, specified as a separate argument (cols), may and will mostly be different.

I do not know why the size is required for other dimensions (MAX_COLS) and it will be very kind of someone to explain. Also please correct, confirm, improve everything as necessary.

Example Code with 1-D array of pointers to model a 2-D array -

  #define MAX_ROWS 20

extern void modify( int rows, int cols, int *a[]);  
extern void input_2d_array(int rows, int cols, int *a[]); 
extern void output_2d_array(int rows, int cols, int *a[]);


int main()

{

int rows = 4, cols = 3;

int* a[MAX_ROWS], i;

for (i=0; i<rows; i++)
    a[i] = (int*) malloc ( cols*sizeof(int) );

input_2d_array(rows, cols, a);

printf("Initially in main array = \n");
output_2d_array(rows, cols, a);

modify(rows, cols, a);

printf("Finally in main array = \n");
output_2d_array(rows, cols, a);

_getch();
return 0;

}

void input_2d_array(int rows, int cols, int *a[])
{

int i, j;

for (i = 0; i < rows; i++)
    for (j = 0; j < cols; j++)
    {
        printf("Please enter the elements for row %d and column %d of a \n", i + 1, j + 1);
        scanf_s(" %d", (a+(i*cols)+j) );
    }

return;
}

void output_2d_array(int rows, int cols, int *a[])
{
int i, j;

for (i = 0; i < rows; i++)
{
    for (j = 0; j < cols; j++)
    {
        printf(" %d", *(a + (i*cols) + j) );
    }
    printf("\n");
}

return;
}

void modify(int rows, int cols, int *a[])
{
int i, j;

printf("Initally in modify array = \n");
output_2d_array(rows, cols, a);

for (i = 0; i < rows; i++)
{
    for (j = 0; j < cols; j++)
    {
        *(a + (i*cols) + j) = (*(a + (i*cols) + j)) + 2;
        // *(*(a + i) + j) += 2; // Gives exception
        // *(a[i]+j) += 10; // Gives exception

    }
}

printf("Finally in modify array = \n");
output_2d_array(rows, cols, a);

return;
}

There are some misunderstandings. It is going to take time to explain them.

Fixed width arrays

Your example prototype is (more or less):

//Prototype  
ReturnType function_name(ArrayType array_name[][MAX_COLS], int rows, int cols);

Somewhere, you have a constant definition for MAX_COLS; for sake of argument, it can be:

enum { MAX_COLS = 64 };

This function only accepts arrays that have MAX_COLS columns, though the arrays can have any number of rows. The int cols argument is immaterial to this array's definition. In the calling code, the array must be defined with MAX_COLS (or its equivalent) as the second dimension.

Inside the function, the compiler will interpret a reference array_name[i][j] (i and j being integer types) as:

*(array_name + (i * MAX_COLS + j))

It will never use cols in that calculation. An attempt to pass an array with a different row width to the function leads to — I'm going to call it 'undefined behaviour', though there might strictly be a different interpretation for which sort of undesirable and incompletely specified behaviour is applicable. The result is not going to be what you expect. If you pass a narrower array, you may well index out of bounds of the actual array; if you pass a wider array, you probably won't run out of bounds, but (as when accessing out of bounds), you won't be accessing the elements you expect to access because the computation will be based on MAX_COLS, not the function argument cols.

Variable length arrays

Using a variable length array (VLA), you could revise your function to:

ReturnType function_name(int rows, int cols, ArrayType array_name[rows][cols]);

Note that the size variables must be defined before they are used; the size parameters must precede their use in an array definition.

Now, inside the function, the compiler will interpret array_name[i][j] (as before) as:

*(array_name + (i * cols + j))

You can pass any shape of array as long as you get the rows and cols parameters correct.

There are a variety of other notations that could be used in the prototype for the function taking a VLA, including these:

ReturnType function_name(int rows, int cols, ArrayType array_name[*][*]);
ReturnType function_name(int rows, int cols, ArrayType array_name[][*]);

However, the function definition would need to have cols appear before the array definition:

ReturnType function_name(int rows, int cols, ArrayType array_name[rows][cols]) { … }
ReturnType function_name(int rows, int cols, ArrayType array_name[][cols]) { … }

And with the 'unsized' leading dimension, you could (if you were perverse enough) write:

ReturnType function_name(int cols, ArrayType array_name[][*], int rows);
ReturnType function_name(int cols, ArrayType array_name[][cols], int rows) { … }

My own view is that it is simpler to maintain the code if the function prototype declaration exactly matches the function definition line, so I'd not use the notations with * in the prototypes. I'd also use the explicit ArrayType array_name[rows][cols] notation, indicating which parameter specifies each size. This matters if you do a matrix multiplication function, for example:

void MatrixMultiply(int r1, int c1, int c2,
                    Data m1[r1][c1], Data m2[c1][c2], Data result[r1][c2]);

Whether the compiler will report problems with matrix size mismatches is open to debate, but the opportunity is there. If you prefer, you could have a redundant r2 parameter to specify the row size of the m2 matrix, but then you've got problems if r2 != c1, and it is harder for the compiler to help — you're reduced to assertions or other error reporting mechanisms to indicate that nothing useful was done to the result because the matrix sizes were not compatible for multiplication.

I'm not sure whether I've deconstructed all the misunderstandings in your question; I suspect not.

Arrays of pointers vs 2D arrays

From a comment:

If my function signature is void modify(int rows, int cols, int *a[]) then how do I access a[i][j] and &a[i][j] in the called function?

This requires an array of pointers to int, so you have to set up the array differently from before (in the calling code). However, inside the function, you simply write:

int x = a[i][j];
int *y = &a[i][j];
int *z = a[i] + j;

The expressions for y and z are equivalent; I'd probably use the former.

Note that the 'behind the scenes' calculation for x is different here from the formula used for a[i][j] when passing an array:

int x = *(*(a + i) + j);

There are two memory references, the first to read the pointer a[i], and the second to read a[i][j] (with two explicit additions but no explicit multiplication, though the subscript additions have to be scaled by the size of int * and int), whereas with the array notation, there was only one memory reference (with two explicit additions and one explicit multiplication — and only one scaling operation by the size of int).

The same comment also says:

I tried a[i]+j and (a[i]+j) combination as well as *(a+(i*cols)+j) and (a+(i*cols)+j) and none is working.

There's a good chance I've not managed to add * symbols in the right places, especially in the 'as well as' portion of the sentence. Please provide the correct notation in a new extra (or replacement) comment, and I can dissect what you actually typed rather than what I'm guessing you typed.

The value of a[i] + j should give you a pointer to the jth integer in the ith row of the data. You'd have to wrap that as *(a[i] + j) to get the int value. The parenthesized version also gives you the pointer to element a[i][j]; you need a * in front to get the value.

The variations like *(a+(i*cols)+j) are wrong because in this context, you do not need to multiply by the number of columns. There's no requirement the consecutive rows pointed at by a[i] and a[i+1] are contiguous in memory; they could be located in multiple disjoint blocks of memory (and in fact there could be multiple pointers to a single block of memory, too). Within a row, the elements must be contiguous, of course.

It's roughly the difference between int a[][4]:

+---+---+---+---+
| 2 | 3 | 5 | 7 |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
| 7 | 5 | 3 | 2 |
+---+---+---+---+
| 9 | 8 | 7 | 6 |
+---+---+---+---+

and int *a[]:

+------------+       +---+---+---+---+
| 0x010C0304 |------>| 2 | 3 | 5 | 7 |
+------------+       +---+---+---+---+
| 0x020D0408 |------>| 1 | 2 | 3 | 4 |
+------------+       +---+---+---+---+
| 0x030E050C |------>| 7 | 5 | 3 | 2 |
+------------+       +---+---+---+---+
| 0x040F0600 |------>| 9 | 8 | 7 | 6 |
+------------+       +---+---+---+---+

Note that more storage is required to hold the int *a[] data than int a[][4]. Also note that I've made the 4 arrays of numbers in the int *a[] non-contiguous. Also, the rows in the int *a[] example could be of different lengths, provided you know how to access the length (or the lengths are all at least 4 and you don't go beyond the fourth element).

Adapting the MCVE from the question

As I said in the previous section, when you are using an 'array of pointers' notation, using cols in the subscript calculation is wrong. Here's an adaptation of your code — I've had to remove the Windows-specific features such as _getch() and scanf_s() (using 'nothing' and scanf() instead). I've also shown some alternatives; the printing shows some of the alternatives.

#include <stdio.h>
#include <stdlib.h>

#define MAX_ROWS 20

extern void modify(int rows, int cols, int *a[]);  
extern void input_2d_array(int rows, int cols, int *a[]); 
extern void output_2d_array(int rows, int cols, int *a[]);


int main(void)
{
    int rows = 4, cols = 3;

    int *a[MAX_ROWS], i;

    for (i = 0; i < rows; i++)
        a[i] = (int *)malloc(cols * sizeof(int));

    input_2d_array(rows, cols, a);

    printf("Initially in main array =\n");
    output_2d_array(rows, cols, a);

    modify(rows, cols, a);

    printf("Finally in main array =\n");
    output_2d_array(rows, cols, a);

    //_getch();
    return 0;
}

void input_2d_array(int rows, int cols, int *a[])
{
    int i, j;

    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            printf("Please enter the elements for row %d and column %d of a\n", i + 1, j + 1);
            //scanf_s(" %d", (a + (i * cols) + j));
            //scanf(" %d", (a + (i * cols) + j));
            scanf(" %d", &a[i][j]);
            //scanf(" %d", a[i] + j);
            //scanf(" %d", *(a + i) + j);
        }
    }
}

void output_2d_array(int rows, int cols, int *a[])
{
    int i, j;

    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            //printf(" %d", *(a + (i * cols) + j));
            printf(" %d", a[i][j]);
            printf(" (%d)", *(*(a + i) + j));
        }
        printf("\n");
    }
}

void modify(int rows, int cols, int *a[])
{
    int i, j;

    printf("Initally in modify array =\n");
    output_2d_array(rows, cols, a);

    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            a[i][j] = a[i][j] + 2;
            *(a[i] + j) = *(*(a + i) + j) + 2;
            //*(a + (i * cols) + j) = (*(a + (i * cols) + j)) + 2;
            // *(*(a + i) + j) += 2; // Gives exception
            // *(a[i]+j) += 10; // Gives exception
        }
    }

    printf("Finally in modify array =\n");
    output_2d_array(rows, cols, a);
}

Example run (program mda17):

$  mda17
Please enter the elements for row 1 and column 1 of a
23
Please enter the elements for row 1 and column 2 of a
24
Please enter the elements for row 1 and column 3 of a
25
Please enter the elements for row 2 and column 1 of a
26
Please enter the elements for row 2 and column 2 of a
27
Please enter the elements for row 2 and column 3 of a
28
Please enter the elements for row 3 and column 1 of a
99
Please enter the elements for row 3 and column 2 of a
98
Please enter the elements for row 3 and column 3 of a
97
Please enter the elements for row 4 and column 1 of a
96
Please enter the elements for row 4 and column 2 of a
95
Please enter the elements for row 4 and column 3 of a
94
Initially in main array =
 23 (23) 24 (24) 25 (25)
 26 (26) 27 (27) 28 (28)
 99 (99) 98 (98) 97 (97)
 96 (96) 95 (95) 94 (94)
Initally in modify array =
 23 (23) 24 (24) 25 (25)
 26 (26) 27 (27) 28 (28)
 99 (99) 98 (98) 97 (97)
 96 (96) 95 (95) 94 (94)
Finally in modify array =
 27 (27) 28 (28) 29 (29)
 30 (30) 31 (31) 32 (32)
 103 (103) 102 (102) 101 (101)
 100 (100) 99 (99) 98 (98)
Finally in main array =
 27 (27) 28 (28) 29 (29)
 30 (30) 31 (31) 32 (32)
 103 (103) 102 (102) 101 (101)
 100 (100) 99 (99) 98 (98)
$

How do i pass an array function without using pointers, You can put the array into a structure like this: struct int_array { int data[128]; }; This structure can be passed by value: void meanval(struct int_array ar); 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 index.

Check this and try to find if array is passed as an array or a pointer to some function:

 char arr[]={'a','b','c'};
 int sizeOfArr = sizeof(arr)/sizeof(arr[0]);

in both the function find size of array using above method where arr[] has been created and where it has been passed - the sizeOfArr will decipher things. This perhaps would clear why size/dimensions have been passed explicitly - this is all I can make out of your entire statement. Correct me if I am wrong.

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  5.11.4. Passing Arrays to Functions To pass an array as a parameter to a function, pass it as a pointer (since it is a pointer). For example, the following procedure sets the first n cells of array A to 0. void zero(int* A, int n) { for(int k = 0; k < n; k++) { A[k] = 0; } } Now to use that procedure: int B[100]; zero(B, 100);

To not use pointers - wrap the array into the struct. Then the entire struct (including the array) will be passed to the function.

How arrays are passed to functions in C/C++, How arrays are passed to functions in C/C++. In C, when we pass an array to a function say fun(), it is always treated as a pointer by fun(). Size may not be needed only in case of '\0' terminated character arrays, size can be determined by  Now that we’ve completed our introduction to pointers, I had really wanted to move on and wrap up our section on using an EEPROM with the I2C protocol today.However, I feel like I would be doing a disservice to you without elaborating further on why we would even want to use pointers in the first place.

Passing 2D array to function (Without Pointers) in C programming , With the help of C Program, I am explaining the concept of passing an array as parameter to Duration: 15:02 Posted: Jul 23, 2018 Passing array to function using call by reference When we pass the address of an array while calling a function then this is called function call by reference. When we pass an address as an argument, the function declaration should have a pointer as a parameter to receive the passed address.

Pass arrays to a function in C, Check if a number is palindrome or not · Program to In C programming, you can pass en entire array to functions. Before we learn Passing array elements to a function is similar to passing variables to a function. C Programming Pointers. In this tutorial we will learn to pass structure pointer to function in C programming language. We learned about how to pass structure to a function in one of the earlier tutorial. So, we will be using that idea to pass structure pointer to a function. Create a structure. In the following example are are creating a student structure.

How to pass Arrays to a Function in C Language?, Whenever we need to pass a list of elements as argument to any function in C We don't return an array from functions, rather we return a pointer holding the that the array exists after the function ends i.e. the array is not local to the function​. Result = 162.50 To pass an entire array to a function, only the name of the array is passed as an argument. However, notice the use of [] in the function definition. This informs the compiler that you are passing a one-dimensional array to the function.

Comments
  • "C allows passing arrays to functions using the array name directly" - no. You cannot pass arrays to or from functions. You can only pass pointers. It's not clear what your actual problem is apart from a missconception about language fundamentals. Please note that you cannot learn C from obscure online tutorials or youtube videos. A good textbook provides information in a structured way.
  • The argument of a function in C is always a value. If the value is a pointer, the exact type of what it points at must be specified (except the special case of a void pointer). In the case of arrays, this is the reason all dimensions other than the first must be specified - in the case of an argument specified as int array_name[][MAX_COLS], array_name is actually passed as a (misnamed) pointer to an array of MAX_COLS integers, not an array.
  • @JonathanLeffler : With all of these arguments, the called function knows the starting address or location of the array and its structure - and hence the called function can access any element it wants. Since, by using just the array name - the starting address was passed - it is a pass by reference - and the changes made by called function will be visible in the calling function without explicit return.
  • @JonathanLeffler : Please correct if its still wrong.
  • Thanks @JonathanLeffler for confirming and your patience. So, this answers my question that it is still passing by reference that works with any local (global will not need to be passed) N- dimension array declared as an N- dimension array using array denotation - rather than using explicit pointer denotation for the same. So, its not necessary to use pointer denotation in declaration in order to be able to pass it by reference. Thanks. I am still trying to understand the second part, which is answered by Peter - looks like that explanation is farther than I have reached yet.
  • clang is the only compiler I've used that reports an issue when a function specifies Data m1[static r1][c1], and you pass an array with the first dimension's length being less than r1 or a null pointer, though the -Warray-bounds and -Wnonnull compiler flags are required to do so. GCC doesn't seem to do so, with or without the same flags specified, but maybe I'm doing something wrong. In any case, this is a fantastic answer. I hope it clears things up for the OP!
  • Thanks @Jonathan Leffler, If my function signature is - > void modify(int rows, int cols, int* a[]) then how do i access a[i][j] and &a[i][j] in the called function ? I tried a[i]+j and (a[i]+j) combination as well as *(a+(icols)+j) and (a+(i*cols)+j) and none is working.
  • I've added a new section at the end of the answer attempting to address your comment. However, I'm not sure I interpreted the placement of * characters correctly. Please create a new comment, using backticks …`int *a[]`… around the code in the comment. Then I can address what you really wanted to type, rather than the idiosyncratically italicized version produced by SO MarkDown.
  • @JonathanLeffler Can we do screen sharing/chat and rectify the code ? I tried passing variable sized array by all methods mentioned in books, but havent got it to work so far - not by declaring it as a 2-D array, nor as a 1-D array of pointers. The only method that worked is giving everything fine - but when i try to add 2 to an int element - it is adding 8 , for 5 it adds 20 to it - I think it is inferring it as an int pointer and doing pointer arithmetic (int is 4 bytes here), although with same notation scanf and printf are able to input and output data correctly from different functions.
  • If you post your MCVE (minimal reproducible example) code in the question, I can address the issues in that code in another extension to my answer.