C: Overwrite Array2D values not working when using function

I want max to have the content of tmp_max. max is dynamically allocated. tmp_max size is known.

Copying the values is working correctly when I hardcode it but it doesn't work when I create a function to copy the values. Why is that?

//This code works
int** max;
init2D(&max,3,4);

int tmp_max[3][4] = {{3,3,2,2}, {1,2,3,4}, {1,3,5,0}};

for(int i = 0 ; i < 3; i++)
    for(int j = 0 ; j < 4; j++)
        max[i][j] = tmp_max[i][j];

assert(max[0][1] == 3); 

//This one crashes
void copyArray2D(int a, int b, int*** tab,int*** tab2){
    for(int i = 0 ; i < a; i++)
        for(int j = 0 ; j < b; j++)
            tab2[i][j] = tab[i][j];
}

int** max;
init2D(&max,3,4);

int tmp_max[3][4] = {{3,3,2,2}, {1,2,3,4}, {1,3,5,0}};
copyArray2D(3,4,&tmp_max,&max); //crash

assert(max[0][1] == 3);

Note:

Using void copyArray2D(int a, int b, int** tab,int** tab2){and copyArray2D(3,4,max,tmp_max); isn't working either.

Using void copyArray2D(int a, int b, int** tab,int** tab2){and copyArray2D(3,4,&max,&tmp_max); isn't working either.

void init2D(int ***data_ptr, int x, int y) {
    int **data = (int **) malloc(sizeof(int *) * x);
    for (int k = 0; k < x; k++)
        data[k] = (int *) malloc(sizeof(int) * y);
    *data_ptr = data;
}

Answers


Your second function has too many stars. You hadn't shown the init2D function when I first wrote an answer, so I had to guess what you'd done with that (but the code is now in the question and is close enough to what I produced that the difference is immaterial — except I do error check the allocations). Here's a (rewritten) version of the code (the first version hadn't been near a compiler, and I completely missed a crucial detail). Note that int ** is not the same as int arr[N][M] or variations on the theme — even if you use the same notation to access both.

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

static void copyArray2D(int a, int b, int **dst, int src[a][b])
{
    for (int i = 0; i < a; i++)
        for (int j = 0; j < b; j++)
            dst[i][j] = src[i][j];
}

static void oom(void)
{
    fprintf(stderr, "Out of memory\n");
    exit(1);
}

static void init2D(int ***arr, int a, int b)
{
    (*arr) = malloc(a * sizeof((*arr)[0]));
    if (*arr == 0)
        oom();
    for (int i = 0; i < a; i++)
    {
        (*arr)[i] = malloc(b * sizeof((*arr)[0][0]));
        if ((*arr)[i] == 0)
            oom();
    }
}

static void dump_2d_array(int a, int b, int arr[a][b])
{
    for (int i = 0; i < a; i++)
    {
        for (int j = 0; j < b; j++)
            printf(" %2d", arr[i][j]);
        putchar('\n');
    }
}

static void dump_2d_pointers(int a, int b, int **arr)
{
    for (int i = 0; i < a; i++)
    {
        for (int j = 0; j < b; j++)
            printf(" %2d", arr[i][j]);
        putchar('\n');
    }
}

int main(void)
{
    int **max;
    init2D(&max, 3, 4);

    int tmp_max[3][4] = { { 3, 3, 2, 2 }, { 1, 2, 3, 4 }, { 1, 3, 5, 0 } };
    copyArray2D(3, 4, max, tmp_max);
    printf("2D array:\n");
    dump_2d_array(3, 4, tmp_max);
    printf("List of pointers:\n");
    dump_2d_pointers(3, 4, max);
    return 0;
}

Output from running that code:

2D array:
  3  3  2  2
  1  2  3  4
  1  3  5  0
List of pointers:
  3  3  2  2
  1  2  3  4
  1  3  5  0

Note that I've not written a free function, so the memory is leaked.

Be wary of 3-Star Programming.


Your compiler should complain about copyArray2D(3,4,&tmp_max,&max).

You must fix any issues identified by your compiler before trying to run your code (running any such executable based on broken code is meaningless).

One problem is that copyArray2D says int*** when it should say int**.

After fixing that, the main issue here is that you have written copyArray2D so that it only works with an array of pointers. (You are simulating a 2-D array by allocating an array of pointers, and then making each pointer point to a separate allocation representing each row).

This works when you use init2D because the init2D function allocates an array of pointers etc.

However int tmp_max[3][4] is a block of 12 contiguous ints. There are no pointers. This is not compatible with copyArray2D.

Your options are:

  • Use int **tmp_max and use init2D to allocate it, instead of int tmp_max[3][4]
  • Make another version of copyArray2D which works on a contiguous 2-D array.
  • Use an ugly macro

void copyArray2D(int a, int b, int tab[a][b],int*** tab2){
    for(int i = 0 ; i < a; i++)
        for(int j = 0 ; j < b; j++)
            (*tab2)[i][j] = tab[i][j];
}

copyArray2D(3,4,tmp_max,&max);

Need Your Help

Add SoapHeader to org.springframework.ws.WebServiceMessage

java web-services spring soap spring-ws

How can I add an object into the soap header of a org.springframework.ws.WebServiceMessage

Why won't Cocoa Pods gem update?

gem cocoapods

Anyone know why 'sudo gem update cocoapods' would return 'Nothing to update', even though I'm running 0.27.1, which is not the latest (0.28.0)?