Search code examples
carraysmultidimensional-arrayfunction-parameter

I need a straightforward example of passing an 2D array to a function in C


I would like to create a C function that takes a 2D array of doubles as a parameter and operates on that array via indexing, e.g. printf("%f ", array[i][j]).

What I've been able to piece together from various examples and SO questions is something like this:

void printArray(double **array, int m, int n)
{
    int i, j;
    for (i = 0; i < m; i++) 
    {
        for (j = 0; j < n; j++) 
        {
             printf("%f ", array[i][j]);
        }
    printf("\n");
    }
}

In main, I'm able to successfully print the array like so:

int i, j, k = 0, m = 5, n = 6;
double **a = malloc(m * sizeof(*a));

//Initialize the arrays
for (i = 0; i < m; i++) 
{
    a[i] = malloc(n * sizeof(*(a[i])));
}
for (i = 0; i < m; i++) 
{
    for (j = 0; j<n; j++) 
    {
        k++;
        a[i][j] = k;
    }
}

printArray(a, m, n);

However, when I try to initialize an array to some given values and then call:

double a[5][6] = { { 1, 2, 3, 4, 5 ,6},
                   { 1, 2, 3, 4, 5, 6},
                   { 1, 2, 3, 4, 5, 6},
                   { 1, 2, 3, 4, 5, 6},
                   { 1, 2, 3, 4, 5, 6} };

printArray(a, 5, 6);

I am met with the following error:

Unhandled exception at 0x011514D3 in Example.exe: 0xC0000005:
Access violation reading location 0xA1F8E3AC.

Can someone explain what my mistake is and how to fix it? edited

Please note that, for the purposes of the function definition, I will know the size of the array at run time but not compile time. Also, I'm compiling on Windows with VisualStudio 2013.


Solution

  • double a[5][6] has type double[][6], which is not the same as double**. double** is a pointer to a pointer to a double. double[][6] is a compiler-managed data type that represents a two-dimensional array.

    What's going on here is that the double[][6] you created is being silently cast to a double** in your invocation of printArray.

    If your function is going to take a double**, you need to pass it a double**. You can initialize the array contents by filling each member array individually:

    double row1[3] = {3, 4, 5};
    a[1] = row1;
    

    This works around the problem; because the double[] is stored by the compiler as a contiguous array of double values, casting it to double* implicitly as above is safe.

    Another solution is to change the function to take a "real" double[][6], instead of a pointer-pointer. How you would do this with non-fixed-size arrays is up to your particular off-brand of C; it's not part of the C standard so far as I know.

    A third solution is to build the array row by row with malloc and fill it cell by cell with a[0][0] = 1 and so forth. You already have this in your question, and it works correctly.

    A final thing to be aware of is that you are allocating a on the stack: when your main function exits, accessing it will result in undefined behavior.