简体   繁体   中英

Allocating memory for multiplying two matrices

A few while back I wrote this code to multiply two matrices. The function mat_mult is called in the main method. I wanted to write something which could take unknown matrix sizes and then allocate memory as needed. I seem to be getting a problem when I output the resultant matrix in the main method. If I do a printf in the mat_mult method the matrix entries are just fine.

Why is the C matrix in the main method not showing correctly? Also the way I am freeing the memory, is it the right method?

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

void mat_mult(int* p, int* q, int* r, int numP)
{
    int i, j, k, sumC=0;

    for (i = 0; i < numP; i++)
    {
        for (j = 0; j < numP; j++)
        {
            for (k = 0; k < numP; k++)
            {
                sumC = sumC + p[i*numP + k]*q[k*numP + j];
            }
            r[i*numP + j] = sumC;
            sumC = 0;
        }
    }
    for(i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", r[i*numP + j]);
        }
        printf("\n");
    }
}

int main()
{
    int A[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int B[3][3] = {{3, 2, 1}, {6, 5, 4}, {9, 8, 7}};


    int i, j;
    int sizA = sizeof(A)/sizeof(A[0]);

    //int C[3][3] = {0};

    /* sizA is the width of the array */
    int **C = calloc(sizA, sizeof(int*));
    for(i = 0; i < sizA; i++)
    {
        /* sizA is the height */
        C[i] = calloc(sizA, sizeof(int));
    }

    for(i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", C[i][j]);
        }
        printf("\n");
    }
    mat_mult(A[0], B[0], C[0], sizA);


    for(i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", A[i][j]);
        }
        printf("\t");
        for (j = 0; j < 3; j++)
        {
            printf("%d ", B[i][j]);
        }
        printf("\t");
        for (j = 0; j < 3; j++)
        {
            printf("%d ", C[i][j]);
        }
        printf("\n");
    }
    free(C[0]);
    free(C);
    return 0;
}

Here is the output from the program above.

0 0 0
0 0 0
0 0 0
42 36 30
96 81 66
150 126 102
1 2 3   3 2 1   42 36 30
4 5 6   6 5 4   150 126 102
7 8 9   9 8 7   0 0 0

Process returned -1073741819 (0xC0000005)   execution time : 12.472 s
Press any key to continue.

PROBLEM RESOLVED

@Jayesh

Thank you very much friend. Your last suggestion worked. I am only reproducing relevant parts of the code.

    int i, j;
    int sizA = sizeof(A)/sizeof(A[0]);

//    int C[3][3] = {0};

    /* sizA is the width of the array */
//    int **C = calloc(sizA, sizeof(int*));
//    for(i = 0; i < sizA; i++)
//    {
//        /* sizA is the height */
//        C[i] = calloc(sizA, sizeof(int));
//    }

    int (*C)[sizA] =  calloc(sizA*sizA, sizeof(int*));
    /* Rest of the Code*/

    free(C);

And here is how the output looks like.

0 0 0
0 0 0
0 0 0
42 36 30
96 81 66
150 126 102
1 2 3   3 2 1   42 36 30
4 5 6   6 5 4   96 81 66
7 8 9   9 8 7   150 126 102

Process returned 0 (0x0)   execution time : 0.085 s
Press any key to continue.

Still wondering why the first method did not work. But thanks again to all of you and Jayesh in particular.

Also the way I am freeing the memory, is it the right method?

No( call free about how many times you called calloc\\malloc ). To free the memory use

for(i = 0; i < sizA; i++)
{
 free(C[i]); 
}
free(C);

I prefer method for memory allocation of matrix like

int (*C)[sizA] =  calloc(sizA*sizA, sizeof(int*));

And just free it by

free(C);

See more details about different ways to allocate array memory

The problem is in the way that you're allocating memory and using it. Within your matmult function you have this code:

r[i*numP + j] = sumC;

which treats the result matrix r as a single-dimensioned linear array. That's fine and will work, but it means that you must also allocate it that way. Your main routine then becomes this:

int main()
{
    int A[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int B[3][3] = {{3, 2, 1}, {6, 5, 4}, {9, 8, 7}};

    int i, j;
    int sizA = sizeof(A)/sizeof(A[0]);

    /* sizA is the width of the array */
    int *C = calloc(sizA*sizA, sizeof(int));

    for(i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", C[i*3+j]);
        }
        printf("\n");
    }
    mat_mult(A[0], B[0], C, sizA);

    for(i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", A[i][j]);
        }
        printf("\t");
        for (j = 0; j < 3; j++)
        {
            printf("%d ", B[i][j]);
        }
        printf("\t");
        for (j = 0; j < 3; j++)
        {
            printf("%d ", C[i*3+j]);
        }
        printf("\n");
    }
    free(C);
    return 0;
}

An alternative approach would be to address all three arrays in this way rather than using multidimensional indexing. It's not pretty but it works.

Alternatively, for a nicer syntax, you might consider C++ for this kind of application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM