Home > Net >  Return type of function for this odd way of creating 2D array
Return type of function for this odd way of creating 2D array

Time:10-29

Freaky way of allocating 2D array

I have used an an adaptation of the code shown in the answers of the referenced post to create an array of strings:

char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));

I realize that for extremely large arrays, this method would not be optimal as a single large block of contiguous memory becomes very expensive when attempting to allocate. But when creating small to medium sized arrays, the advantages can be attractive. Eg. This method uses only a single call to malloc(), to allocate a single contiguous block memory, therefore requires only one call to free() when done using it, making it a desirable alternative to more idiomatic methods I have seen. (those using multiple calls to malloc() and free(),)

So, I would like to encapsulate it into a function, but thus far I have not discovered what return type is compatible:

T  CreateStringArray(int rows, int cols)
{
    char (*string)[rows] = malloc(sizeof(char [rows][cols]));
    memset(string, 0, sizeof(char [rows][cols]));

    return T;
}

What form of T would work with this function?

CodePudding user response:

You can try something like that:

void * CreateStringArray(int rows, int cols)
{
    char (*string)[cols] = malloc(sizeof(char [rows][cols]));
    memset((void*)string, 0, sizeof(char [rows][cols]));

    return string;
}

int main()
{
    char (*p)[4] = (char (*)[4])CreateStringArray(3, 4);
}

Note that char (*string)[cols] shall be defined with cols not rows. because string is a pointer to a one-dimensional array of cols elements.

CodePudding user response:

You would like to return char (*)[rows], but this is a variably-modified type, and only objects (not functions) declared with no linkage (unlike all functions) at block or function prototype scope can have variably-modified types (C17 6.7.6.2/2).

Therefore, the best you can do for the return type of of your function is char * or void *.

However, you could patch that up with a macro:

void *CreateStringArray_func(int rows, int cols)
{
    char (*string)[rows] = malloc(sizeof(char [rows][cols]));
    memset(string, 0, sizeof(char [rows][cols]));

    return string;
}

#define CreateStringArray(rows, cols) \
    ((char (*)[rows]) CreateStringArray_func(rows, cols))

But in that particular case, I would probably just use

#define CreateStringArray(rows, cols) calloc(rows, cols)

You can add the cast to the latter, too, but I omit it on the principle of not casting the result of allocation functions.

CodePudding user response:

If I have understood correctly the function should return the allocated pointer within the function,

The pointer has the type char (*)[cols] but when the function is declared the return type of the function knows nothing about the variable cols.

In this case the function should be declared like

void * CreateStringArray(int rows, int cols) )
{
    char (*string)[rows] = malloc(sizeof(char [rows][cols]));
    memset(string, 0, sizeof(char [rows][cols]));

    return string;
}

And in the caller you can write

char ( *string )[cols] = CreateStringArray( rows, cols );
  • Related