Search code examples
cmultidimensional-arrayreturn-typefunction-declarationvariable-length-array

return 2D array from C function


Inspired by this question. I created this function:

char** char2Da (int r, int c) {

    char (*p)[c] = malloc(sizeof(char[r][c]));
    // come code filling 2D array
    return (char**) p;
}

Unfortunately it does not work. Why? Is it possible to return a pointer to 2D array in C and preserve [][] notation using method from above? If it is not, why? What am I missing here?
I know there is workaround by creating outside array, passing it by ref to function. But its a bit ugly and I would love to encapsulate everything in one function.

Bare in mind that I have PHP and JavaScript background and there you just create arr[][] and return it from function. No fuss.


Solution

  • The types char ** and char ( * )[c] are different types. For example dereferencing the first pointer of the type char ** you will get the value stored in first characters of the first row of the allocated array that is not a pointer.

    You can do the task the following way

    void * char2Da (int r, int c) {
    
        char (*p)[c] = malloc(sizeof(char[r][c]));
        // come code filling 2D array
        return p;
    }
    

    and then in the caller write

    char ( *p )[c] = char2Da( r, c );
    

    Here is a demonstrative program

    #include <stdio.h>
    #include <stdlib.h>
    
    void * f( size_t r, size_t c )
    {
        char ( *p )[c] = malloc( sizeof( char[r][c] ) );
        
        return p;
    }
    
    
    int main(void) 
    {
        size_t r = 2, c = 3;
        
        char ( *p )[c] = f( r, c );
        
        free( p );
        
        return 0;
    }
    

    Or another demonstrative program.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void * f( size_t r, size_t c )
    {
        char ( *p )[c] = malloc( sizeof( char[r][c] ) );
    
        char value = 'A';
        
        for ( size_t i = 0; i < r; i++ )    
        {
            memset( p[i], value++, c );
            p[i][c-1] = '\0';
        }
        
        return p;
    }
    
    
    int main(void) 
    {
        size_t r = 2, c = 3;
        
        char ( *p )[c] = f( r, c );
        
        for ( size_t i = 0; i < r; i++ ) puts( p[i] );
        
        free( p );
        
        return 0;
    }
    

    The program output is

    AA
    BB
    

    If c is a compile-time constant that is you are not allocating a variable length array then the function declaration could look for example like

    #define C 10
    
    char ( *char2Da (int r ) )[C];