3

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?

5
  • 1) No, but try [] (array of unspecified size). 2) Yes, you have the syntax correct. The most equivalent alternative would be to just return a normal pointer. You'd then either declare arr as int *arr = foo(row, col); and use it as arr[i * col + j] (or *(arr + i * col + j)), or you'd cast the return value to match the declaration of arr as in int (*arr)[col] = (int (*)[col])foo(row, col); to be able to use arr[i][j] (or *(*(arr + i) + j) since you're fond of using pointer notation rather than the more readable equivalent using array notation). Commented May 27, 2016 at 18:05
  • @ChronoKitsune I tried that, but I wasn't sure if that is OK, hence the Question. I could type [0] too. :) 2) I need this sintax int (*arr)[col] Commented May 27, 2016 at 18:09
  • @ChronoKitsune I already have This solution, but this is not what I need. Commented May 27, 2016 at 18:11
  • The syntax [] formally denotes an array of incomplete type (C11 section 6.7.6.2p4). Returning a pointer to that array is allowed. However, you can't dereference that pointer until the pointer has been assigned to an array with complete type. For example, if you declared int (*arr)[] = foo(row, col); then you couldn't do *arr or arr[...] at all. int (*arr)[col] = foo(row, col); is allowed, and you can then successfully use the pointer as desired because int (*arr)[col] is a pointer to a complete type. Commented May 27, 2016 at 18:32
  • @ChronoKitsune This mean in my case, that is OK. Commented May 27, 2016 at 18:36

1 Answer 1

5

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 ints. 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 ints. Equivalently, you can read that as saying that the thing foo points to is an array of 3 ints, 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 ints.

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

4 Comments

Do you mean something like This if so is not what i need, if no could you please provide me a DEMO where I have a pointer to an array in main function and a function which does that?
Or is ok to just use (like @ChronoKitsune pointerd) this [] (array of unspecified size) ==> int (*func(size_t row, size_t col))[]; ?
@Michi, yes, your IdeaOne example is what I was describing. Yes, you can use the [] the form ChronoKitsune suggested, but I think you would find that harder to work with in pretty much every way.
Thank you, I needed to know if that is Legal. Please provide this to you Answer.

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.