简体   繁体   中英

Function returning a Pointer to an Array

I managed to succed to work with Variable length Arrays in C and I have now the following:

#include <stdio.h>
#include <stdlib.h>

int (*foo(size_t row, size_t col))[3];

int main(void){
    size_t row, col;


    printf("Give the ROW: ");
    if ( scanf("%zu",&row) != 1){
        printf("Error, scanf ROW\n");
        exit(1);
    }

    printf("Give the COL: ");
    if ( scanf("%zu",&col) != 1){
        printf("Error, scanf COL\n");
        exit(2);
    }

    int (*arr)[col] = foo(row, col);

    for ( size_t i = 0; i < row; i++){
        for( size_t j = 0; j < col; j++){
            printf("%d ",*(*(arr+i)+j));
        }
    }

    free(arr);
}


int (*foo(size_t row, size_t col))[3]{
    int (*arr)[col] = malloc(row * col * sizeof(int));
    int l=0;

    if (arr == NULL){
        printf("Error, malloc\n");
        exit(3);
    }

    for ( size_t i = 0; i < row; i++){
        for( size_t j = 0; j < col; j++){
            *(*(arr+i)+j) = l;
            l++;
        }
    }

    return arr;
}

Output:

Give the ROW: 2
Give the COL: 5
0 1 2 3 4 5 6 7 8 9

Now This:

int (*foo(size_t row, size_t col))[3]{ /* code */ }

means, if I understood right that declares foo as a function with two parameters (size_t row, size_t col) that returns a pointer to an array 3 of int.

I'm not entirely capable to understand this kind of Function and it is more complicated for me now working with Variable length Arrays when the size is known only at run time, but I find this a good thing. I am working only with C11 standard.

Any way here int (*foo(size_t row, size_t col))[3] I have this [3] which I'm not clear about how it works and how can I make it possible on run time (of course only if is possible), something like int (*foo(size_t row, size_t col))[SIZE] .

I read some books about C , but there is no exactly explanations about this situation and Google doesn't help either, so I have two Questions:

1) Is this posiible int (*foo(size_t row, size_t col))[SIZE] , where SIZE has to be parameter? Or should i declare this Function in another way?

2) is this the right way for what I tried here, or there is another alternative?

I'm only trying to return a pointer to an array where the size is know at run time and not compile time. The call of malloc and free happens only one time and this is a good approach, because whenever malloc is called, our program disturb kernel to allocate memory and mark page as writable.So this method have less over head on kernel . It can be written in one malloc working with VLA's

EDIT:

@ChronoKitsune said that i should use/try [] (array of unspecified size) in which case the function will become like this:

int (*foo(size_t row, size_t col))[]{ /* code */ }

Is this what i should use?

Any way here int (*foo(size_t row, size_t col))[3] I have this [3] which I'm not clear about how it works

Type declarations are most easily read from inside out. I'll start simple, and build up to your example. If you write

int foo[3];

or

int (foo)[3];

you are declaring foo as an array of 3 int s. The parentheses here serve a precedence-directing grouping function, just like in expressions, but they are unnecessary because the type is interpreted the same way in both cases.

If you write

int (*foo)[3];

you are declaring foo to be a pointer to an array of 3 int s. Equivalently, you can read that as saying that the thing foo points to is an array of 3 int s, with it being implicit that foo is a pointer. In this case the parentheses are necessary; without them you would be declaring foo as an array of 3 int * .

If you write

int (*foo(size_t row, size_t col))[3];

you are declaring that foo is a function taking two arguments of type size_t , whose return value points to an array of 3 int s.

and how can I make it possible on run time (of course only if is possible), something like int (*foo(size_t row, size_t col))[SIZE] .

If SIZE is not a compile-time constant then you cannot do that. C2011 holds that

If an identifier is declared as having a variably modified type, it shall [...] have no linkage, and have either block scope or function prototype scope. [...]

(6.7.6.2/2)

In other words, because all functions have file scope and either internal or external linkage, function return types cannot be VLAs, pointers to VLAs, or any such type (these are "variably-modified" types).

Generally, in such cases one returns a pointer to the first element of the array rather than a pointer to the whole array. The pointed-to address is the same either way, but the type is different:

int *foo(size_t row, size_t col);

The return type does not carry information about the length of the pointed-to array, but if C allowed functions to return variably-modified types then that would rely anyway on a mechanism by which the code could know the variable dimensions in any particular context. In other words, if you don't know the expected array length independent of the function's return type, then there's no way you could have used a variably-modified return type anyway.

If indeed you need the function to return both a pointer to a runtime-determined number of elements and also the number of elements, then you can return a struct containing both, or you can return one or both values via pointer parameters.

Update :

It is also possible to declare your function to return a pointer to an array of unspecified size, as @ChronoKitsune suggested. The syntax would be

int (*bar(size_t row, size_t col))[];

, but you will find that return type harder to use in almost every way. For example, it is trickier and uglier to declare variables that can hold the return value:

int (*array_ptr)[] = bar(x, y);

and to access elements of the pointed-to array:

int z = (*array_ptr)[1];

Contrast that with

int *ptr = foo(x, y);
int w = ptr[2];

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