函数返回一个指向数组的指针 [英] Function returning a Pointer to an Array

查看:156
本文介绍了函数返回一个指向数组的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法赢得成功在 C 有变长数组工作,我现在有以下几点:

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;INT(*富(为size_t行,为size_t COL))[3];诠释主要(无效){
    为size_t行,列;
    的printf(给ROW:);
    如果(scanf的(%つ,&放大器;!行)= 1){
        的printf(错误,scanf函数ROW \\ n);
        出口(1);
    }    的printf(给COL:);
    如果(scanf函数(%俎,&安培;!COL)= 1){
        的printf(错误,scanf函数COL \\ n);
        出口(2);
    }    INT(* ARR)[COL] = foo的(行,列);    用于(为size_t我= 0; I<排;我++){
        用于(为size_t J = 0; J<西; J ++){
            的printf(%d个*(*(ARR + I)+ J));
        }
    }    免费(ARR);
}
INT(*富(为size_t行,为size_t COL))[3] {
    INT(* ARR)[COL] =的malloc(行* COL *的sizeof(INT));
    int类型l = 0;    如果(ARR == NULL){
        的printf(错误,malloc的\\ n);
        出口(3);
    }    用于(为size_t我= 0; I<排;我++){
        用于(为size_t J = 0; J<西; J ++){
            *(*(ARR + I)+ J)= 1;
            升++;
        }
    }    返回ARR;
}

输出:

 给该行:2
给COL:5
0 1 2 3 4 5 6 7 8 9

现在这样:

  INT(*富(为size_t行,为size_t COL))[3] {/ * code * /}

意味着,如果我明白,返回一个指向一个int数组3右声明富与两个参数(为size_t行,为size_t COL)的功能。

我不完全能够理解这种功能,它是更复杂,我现在变长数组时的大小只在运行时知道,但我觉得这是一件好事。我与 C11 标准只工作。

任何方式在这里 INT(*富(为size_t行,为size_t COL))[3] 我有这样的[3]这我不清楚它是如何工作我怎样才能使人们有可能在运行时(当然前提是可能的),像 INT(*富(为size_t行,为size_t COL))[SIZE]

我读 C 一些书,但没有对这种情况的解释准确和谷歌也没有帮助,所以我有两个问题:

1)本posiible INT(*富(为size_t行,为size_t COL))[SIZE] ,其中大小必须参数?或者我应该声明此功能的另一种方式?

2),这是什么我想在这里以正确的方式,或者有另一种选择?

我只是想返回一个指向一个数组,其中大小知道在运行时,不编译时间。 的malloc 免费的通话只发生一次,这是一个很好的方法,因为每当的malloc 被调用时,我们的程序干扰内核分配内存和标记页面writable.So这种方法有较少的头顶上内核
它可以写在一个的malloc 与VLA的工作。

编辑:

@ChronoKitsune说,我应该使用/尝试 [] (未指定大小的数组)在这种情况下功能将变成这个样子:

  INT(*富(为size_t行,为size_t COL))[] {/ * code * /}

这是我应该用什么?


解决方案

  

任何方式在这里 INT(*富(为size_t行,为size_t COL))[3] 我有这样的 [3] 这我不清楚它是如何工作


类型声明是最容易从里面出来读。我会从简单的开始,并建立你的例子。如果你写

  INT富[3];

  INT(富)[3];

您声明为3 INT 秒的数组。这里的括号服务于precedence导向分组功能,就像前pressions,但他们是不必要的,因为类型是间$ P $在这两种情况下PTED以同样的方式。

如果你写

  INT(*富)[3];

您声明是一个的指针的到数组3 INT 秒。等价地,你可以阅读的话说,事情指的是3 INT 秒的阵列,它是隐含的是一个指针。在这种情况下,括号是必要的;没有他们,你会声明为3 一个int数组*

如果你写

  INT(*富(为size_t行,为size_t COL))[3];

您声明是采取类型的两个参数的函数为size_t ,其返回值指向一个数组3 INT 秒。


  

和我怎样才能使人们有可能在运行时(当然前提是可能的),像 INT(*富(为size_t行,为size_t COL))[SIZE]


如果尺寸不是一个编译时间常数,那么你不能做到这一点。 C2011认为


  

如果一个标识符被声明为具有可变类型的,应当[...]没有联动,要么块范围或函数原型范围。 [...]


(6.7.6.2/2)

在换句话说,因为所有的功能的文件的范围和内部或外部联动,函数的返回类型不能VLAS,指针VLAS,或任何这样的类型(这些是可变改性的类型)。

一般地,在这种情况下,其中一个返回指针到所述阵列的所述第一元件,而不是一个指向整个阵列。所指向的地址是相同的任一方式,但类型不同的是:

 为int * foo的(为size_t行,为size_t列);

返回类型不携带的长度信息所指向的数组,但如果C允许函数返回可变修饰类型那么无论如何都会依赖于该code可以知道该变量的机制尺寸在任何特定的情况下。换句话说,如果你不知道独立于函数的返回类型的预期数组长度,那么有没有办法,你也可以使用一个可变修饰的返回类型反正。

如果你确实需要的功能都返回一个指向元素的运行时确定的数的元素的数量,那么你可以返回含有一个结构,或者你可以返回1或通过指针参数的两个值。

更新

也可以声明你的函数返回一个指向未指定大小的数组,因为@ChronoKitsune建议。语法是

  INT(*栏(为size_t行,为size_t COL))[];

,但是你会发现,返回类型更难几乎在每一个方式使用。例如,它是棘手和丑陋来声明可以保存返回值的变量:

  INT(* array_ptr)[] =栏(X,Y);

和访问的内容所指向的数组:

  INT Z =(* array_ptr)[1];

对比度与

 为int * PTR = foo的(X,Y);
INT W = ptr的[2];

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 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];

这篇关于函数返回一个指向数组的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆