简体   繁体   中英

C programming - pointers used in functions that work with multidimensional arrays

I have the following 2 functions:

double** transpose(double **a, int r, int c){
    static double trans[100][100];
    int i,j;
    for(i = 0; i < r; i++)
        for(j = 0; j < c; j++)
            trans[j][i] = a[i][j];
    return trans;
}

double(*matrixMultiply(double a[10][10], double b[10][10],
    int rowA, int colB, int colARowB))[10]{
    static double c[10][10];
    int i, j, k;
    for(i = 0; i < rowA; i++)
        for(j = 0; j < colB; j++){
            c[i][j] = 0;
            for(k = 0; k < colARowB; k++)
                c[i][j] += a[i][k]*b[k][j];
        }
    return (double*) c;
}

While I do understand the algorithms, can someone explain me what these 2 functions return (types, pointers...) ? The second seems to return an array, but I thought that functions in C can't return arrays ...

Getting really confused with these pointers...

Also why are the arrays ( trans and c ) declared as static? As far as I get it, when you declare a variable or a function with static it can't be imported for use in another file, but that's defenetely not the case here ...

Both functions are attempting to return pointers to arrays. Both are doing it wrong and fail to compile on my system.

Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T " will be converted ("decay") to an expression of type "pointer to T ", and the value of the expression will be the address of the first element of the array.

In the transpose function, we're returning the expression trans . trans has type "100-element array of T ", where T is "100-element array of double ". It's not the operand of the sizeof or unary & operators, so it is converted ("decays") to an expression of type "pointer to T ", which in this case is "pointer to 100-element array of double " ( double (*)[100] ), NOT "pointer to pointer to double ", ( double ** ).

The compiler should complain about that function. Mine does, like so:

gcc -c -std=c99 -pedantic-errors -Wall transpose.c
transpose.c: In function âtransposeâ:
transpose.c:7: error: return from incompatible pointer type

In the matrixMultiply function, c has type "10-element array of 10-element array of double ", which "decays" to "pointer to 10-element array of double " ( double (*)[10] ). The second function has the right return type - double (*)[10] - but then they MESS IT UP by casting c to double * in the return statement, and we get the same error as before:

gcc -c -std=c99 -pedantic-errors -Wall matrixMultiply.c
matrixMultiply.c: In function âmatrixMultiplyâ:
matrixMultiply.c:11: error: return from incompatible pointer type

They should have just written

return c;

and everything would have been alright.

The way to read that second function definition is as follows:

        matrixMultiply                           -- matrixMultiply
        matrixMultiply(                   )      -- is a function taking
        matrixMultiply( /* some params */ )      -- some parameters (omitted for brevity)
       *matrixMultiply( /* some params */ )      -- returning a pointer
      (*matrixMultiply( /* some params */ ))[10] -- to a 10-element array
double(*matrixMultiply( /* some params */ ))[10] -- of double

Note that the only reason either function has a hope of working (once the type issues are straightened out) is that both trans and c are declared static , meaning that their lifetimes extend over the entire program, not just the lifetimes of their respective functions. Without that static keyword, they would cease to exist after their enclosing functions return, and those pointers would become invalid .

This is not necessarily good practice - these functions are no longer re-entrant and not thread-safe. It would be better to pass the target arrays as parameters to the functions, but be aware that a pointer to a 10-element array is a different, incompatible type from a pointer to an 11-element array - if you have to deal with arrays with different numbers of columns, that could get tricky. VLAs can help with that:

void transpose( int r, int c, double arr[r][c], double trans[c][r] )
{
  ...
}

assuming you have VLAs available (you should on C99 and C2011 systems, although they've been made optional in C2011). If you don't ... this gets harder.

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