Hirosam
Hirosam

Reputation: 13

Copying a pointer of a pointer (matrix) values in C

The problem is the following: I created a dynamic matrix, using pointer to pointer matrix1

I want to create a copy of this matrix into another, matrix2

I want to do that so I can mess with matrix2 without messing with matrix1 So I tried to do the following:

int main()
{
    int **matrix1, **matrix2, size1 = 10, size2 = 2;
    matrix1 = create_matrix(size1, size2);

    //I want to copy the value of matrix1 into matrixq2 and NOT the index
    **matrix2 = **matrix1
}

However the program breaks and show the following: Error

I understand that by the way it look, it would be easier to use the function create_matrix two times, for matrix1 and another for matrix2. But in the way that my original program is that would be too much work, since I do a lot of stuff to have the matrix done. Oh, and by the way, I want to avoid using C++, is there is a way to do it without using it? It would be better for me.

the code 'create_matrix' is the following:

//The program will read a file with the name of endereco, and create a matrix contPx3 out of it
int ** cria_matrix(char endereco[], int contP)
{
    FILE *fPointer;
    int i, contE, auxIndex, auxNum, **processos, cont_line = 0;
    char line[100];
    bool flag = true, flag2;

    fPointer = fopen(endereco, "r");

//Here the creation of the matrix
    processos = (int**)malloc(sizeof(int*) * contP);
    for (i = 0; i < contP; i++)
        processos[i] = malloc(sizeof(int) * 3);



//For now and on, is the rules of how the data will be placed on the matrix
    contP = 0;
    while (!feof(fPointer) && flag)
    {

        memset(&line[0], 'Ì', sizeof(line));
        fgets(line, 100 , fPointer);
//Bassicaly is that in each line there will be 3 numbers only, diveded but as many spaces you want. The numbeer will be placed on the matrix on the determined line they are.
        auxIndex = 0;
        flag2 = false;
        if(line[0] != '#')
            for (i = 0; i < 100; i++)
            {
                if (line[i] != ' ' && line[i] != '\n' && line[i] != '\0' && line[i] != 'Ì')//&&  line[i] != 'à'
                {
                    auxNum = line[i] - '0';
                    processos[contP][auxIndex] = auxNum;
                    auxIndex++;
                    flag2 = true;

                }
            }

        if (flag2)
            contP++;



        cont_line++;
        if (auxIndex != 3 && auxIndex != 0)
        {
            flag = false;
            printf("ERRO na linha: %d No processo: %d\nProvavelmente mais ou menos que 3 numeros separado por espacos\n", cont_line, contP);
        }

    }
    fclose(fPointer);
    if (!flag)
        system("PAUSE");
    return processos;
}

Upvotes: 1

Views: 1318

Answers (3)

Mad Physicist
Mad Physicist

Reputation: 114330

matrix1 points to the array of row pointers, *matrix1 is a pointer to an array holding the first row of actual data, and **matrix1 is the value of first element of the first row. matrix1 and each of its elements are all dynamically allocated arrays.

matrix2 is an uninitialized (trash) pointer in the code you have displayed. It has neither the row pointer nor data buffers allocated.

To achieve your desired result, you need to first allocate the elements of matrix2, then copy just the data portion of matrix1 over.

int **copy_matrix(int **mat, int size1, int size1)
{
    int row;

    int **res = malloc(size1 * sizeof(int *));
    for(row = 0; row < size1; row++) {
        res[row] = malloc(size2 * sizeof(int));
        memcpy(res[row], mat[row], size2 * sizeof(int));
    }
    return res;
}

...

matrix2 = copy_matrix(matrix1, size1, size2);

An alternative would be to allocate a single buffer for the copy. While this is possibly a better way of storing matrices in general, it may not be as useful to you because you will not be able to free the memory of matrix2 the same way that you do for matrix1:

int **copy_matrix(int **mat, int size1, int size2)
{
    int row;
    int **res = malloc(size1 * sizeof(int *));
    res[0] = malloc(size1 * size2 * sizeof(int));

    for(row = 0; row < size1; row++) {
        res[row] = res[0] + row * size2;
        memcpy(res[row], mat[row], size2 * sizeof(int));
    }
    return res;
}

Upvotes: 1

Malcolm McLean
Malcolm McLean

Reputation: 6404

You need to understand the difference between copying pointers, taking shallow copies, and taking deep copies. Consider this

struct employee
{
   char *name;
   float salary;
   int payrollid;
}

There are now three ways of copying an employee

struct employee * emp1;  // points to an employee, set up somehow
struct employee * emp2;  // empty pointer, null or whatever

emp2 = emp1;  // copy pointers. emp1 and emp2 now point to the same object.

Pointer copy

struct employee  employee1;  // employee, set up
struct employee  employee2;  // uninitalised emplyee

memcpy(&employee2, &employee1, sizeof(struct employee)); // shallow copy

Shallow copy

struct employee * emp1;  // points to an employee, set up somehow
struct employee * emp2;  // empty pointer, null or whatever

emp2 = copyemployee(emp1);

struct employee *copyemployee(struct employee *e)
{
   struct employee *answer = malloc(sizeof(struct employee));
   if(!answer)
     goto error_exit;
   answer->name = malloc(strlen(e->name) + 1);
   if(!answer->name)
      goto error_exit;
   strcpy(answer>name, e->name);
   answer->salary = e->salary;
   answer->payroolid = e->payrollid;
   return answer;
error_exit:
   /* out of memory handle somehow, usually by returning null
}

Deep copy

As you can see, even for a simple structure with only one variable-length field, taking a deep copy is quite a bit of work. All have their uses, though shallow copies are probably the least useful and most bug prone of the three.

You simply need to assign to a pointer, probably.

Upvotes: -1

Brad
Brad

Reputation: 486

How bout this-

matrix2 = (int**)malloc(sizeof(int*)*size1);
for(int idx = 0; idx < size1; ++idx) {
    matrix2[idx] = (int*)malloc(sizeof(int)*size2);
    for(int idx2 = 0; idx2 < size2; ++idx2) {
        matrix2[idx][idx2] = matrix1[idx][idx2];
    }
}

Upvotes: 1

Related Questions