Home > Net >  Inconsistent C code output with matrix multiplication algorithm
Inconsistent C code output with matrix multiplication algorithm

Time:11-14

I have written the following code to perform a simple matrices multiplication.

#include <stdio.h>

void op2(float *a_vec, int m, int n, int p, float *b_vec, float *c_vec){
    float (*a)[n] = (float(*)[n]) a_vec;
    float (*b)[p] = (float(*)[p]) b_vec;
    float (*c)[p] = (float(*)[p]) c_vec;
    int i, j, k;

    for (i = 0; i<m; i  ){
        for(j=0; j<p; j  ){
            for(k=0; k<n; k  ){
                c[i][j]  = a[i][k] * b[k][j];
            }
            printf("%.1f ", c[i][j]);
        }
        printf("\n");
    }
    
}

int main(void){
    float *aVec;
    float *bVec;
    float *cVec;
    int m = 2;
    int n = 3;
    int p = 2;

    float a[6] = {
                1,3,1,
                2,2,2
                };

    aVec = &a[0];

    float b[6] = {
        1,3,
        1,2,
        2,2
        };

    bVec = &b[0];
    float c[4];
    cVec = &c[0];

    op2(aVec, m, n, p, bVec, cVec);
}

The resulting vector (printed to output) should be 6.0 11.0 8.0 14.0

Which it is... Most of the time.

However, sometimes it isn't. Sometimes the first value of the array will be incorrect. Most commonly it will be 5.7 or 5.8 5.8 11.0 8.0 14.0

My question is, what am I doing here that is causing this inconsistency? I'm quite new to C and my best guess is that perhaps I'm missing something with relation to the array indices, perhaps I'm running past the end of the array? But I don't see how it would happen inconsistently given that it has the same input, so maybe I'm missing something with pointers?

Have tried: Declaring array variables outside loops, changing values in input arrays.

CodePudding user response:

Having c[i][j] = a[i][k] * b[k][j]; inside your loop only works if the c matrix is initialized to zero. However, the c array float c[4]; in main is declared with no initializer, so it contains garbage, which when you add the results of your multiplication gives you more garbage.

The valgrind memory checking tool finds this bug. Tools like this are invaluable for C debugging, and should become one of the first things you try when faced with a bug. AddressSanitizer (-fsanitize=address) and UBSan (-fsanitize=undefined), both available in GCC and clang, are also very nice, but they happen not to find this bug.

This particular problem can be fixed by defining float c[4] = {0.0};. (As soon as you initialize at least one element of an array, all the rest are automatically initialized to zero.)

  • Related