1

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.

1
  • In this case return the pointer as a void * pointer and then in the caller assign it to a pointer of the type char ( * )[c]. Commented Dec 18, 2020 at 21:35

1 Answer 1

3

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];
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot. So I'll always have to use char(*p)[c] = f( r, c ); c value must be on both sides of = sign? Is there some other/better way to avoid that c value on both sides?
@CoR You are dynamically allocating a variable length array of the type char[r][c]. So the pointer to the element (row) of the array has the type char ( * )[c] that you should use to access elements of the array as it is shown in the second demonstrative program.
@CoR: You can avoid repeating c with char (*p)[c] = f(r, sizeof *p / sizeof **p);. That avoids the repetition, which is generally a good thing for avoiding bugs, but it does add clutter. It is common to have a macro that provides the number of elements of an array: #define NumberOf(x) (sizeof (x) / sizeof *(x)). Then you could write char (*p)[c] = f(r, NumberOf(*p));. It is the sort of thing an expert might use to keep their code orderly, depending on circumstances, but it may be unfamiliar and puzzling to novices.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.