从函数c返回二维数组的正确方法

从函数c返回二维数组的正确方法,c,arrays,function,C,Arrays,Function,我试过这个,但不起作用: #include <stdio.h> int * retArr() { int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; return a; } int main() { int a[3][3] = retArr(); return 0; } #包括 int*retArr() { int a[3][3]={{1,2,3},{4,5,6},{7

我试过这个,但不起作用:

#include <stdio.h>

    int * retArr()
    {
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
    }

    int main()
    {
    int a[3][3] = retArr();
    return 0;
    }
#包括
int*retArr()
{
int a[3][3]={{1,2,3},{4,5,6},{7,8,9};
返回a;
}
int main()
{
int a[3][3]=retArr();
返回0;
}
我发现以下错误:

错误3错误C2075:“a”:数组初始化需要大括号
4 IntelliSense:返回值类型与函数类型不匹配


我做错了什么?

需要返回
int**
,而不是
int

,以便:

int * retArr() {
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
}
该数组具有局部作用域,并且在退出该函数后立即销毁。这意味着
返回a实际上返回一个悬空指针


要解决此问题,请将数组放入全局范围,或使用
malloc()
将数组复制到分配的空间中。

结构是一种方法:

struct t_thing { int a[3][3]; };
然后按值返回结构

完整示例:

struct t_thing {
    int a[3][3];
};

struct t_thing retArr() {
    struct t_thing thing = {
        {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        }
    };

    return thing;
}

int main(int argc, const char* argv[]) {
    struct t_thing thing = retArr();
    ...
    return 0;
}

你面临的典型问题是
inta[3][3]={{1,2,3},{4,5,6},{7,8,9}指函数返回后回收的内存。这意味着您的调用者阅读(未定义的行为)是不安全的

其他方法包括将数组(调用者拥有的数组)作为参数传递给函数,或创建新的分配(例如使用
malloc
)。结构很好,因为它可以消除许多陷阱,但它并不适合所有场景。当结构的大小不是常量或非常大时,可以避免使用按值结构。

\include
#include <stdio.h>

int** retArr()
{
    static int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
}

int main()
{
    int** a = retArr();
    return 0;
}
int**retArr() { 静态int a[3][3]={{1,2,3},{4,5,6},{7,8,9}; 返回a; } int main() { int**a=retArr(); 返回0; }
还可以将返回的变量指定为static。您还必须在main中将变量a声明为int**(而不是指定维度)。

几个问题:

首先,不能通过函数调用初始化数组;语言定义根本不允许它。
char
的数组可以用字符串文本初始化,例如

char foo[] = "This is a test";
wchar\u t
char16\u t
char32\u t
的数组可以使用宽字符串文字进行初始化,否则初始化器必须是大括号内的值列表

其次,你有一个类型不匹配;除非它是
sizeof
或一元
&
运算符的操作数,或者是用于初始化声明中另一个数组的字符串文字,否则“T
的N元素数组”类型的表达式将转换为“指向
T
的指针”类型的表达式,表达式的值将是第一个元素的地址

在函数
retArr
中,表达式中
a
的类型为“int
的三元素数组的三元素数组”;根据上述规则,这将转换为“指向
int
”或
int(*)[3]
”类型的表达式:

int (*retArr())[3]
{
  int a[3][3] = ...;
  return a;
}

但正如布伦丹指出的那样,一旦
retArr
退出
a
就不再存在;返回的指针值最终无效

我们可以通过使用堆内存/使用stdlib分配内存来解决这个问题:

使用stdlib分配内存可以由malloc和calloc完成

创建数组

  • 用于分配5行
  • 用于在每个“i”行中分配5列
  • 因此,我们创建了arr[5][5]
返回数组:

我们只需要发送负责访问上述数组的指针

#include<stdio.h>
#include<stdlib.h>
int **return_arr()
{
    int **arr=(int **)malloc(sizeof(int *)*5);
    int i,j;
    for(i=0;i<5;i++)//checking purpose
    {
        arr[i]=(int *)malloc(sizeof(int)*5);
        for(j=0;j<5;j++)
        {
            arr[i][j]=i*10+j;
        }
    }
    return arr;
}
int main()
{
    int **now;
    now=return_arr();
    int i,j;
    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            printf("%d ",now[i][j]);
        }
        printf("\n");
    }
    return 0;
}
#包括
#包括
int**return\u arr()
{
int**arr=(int**)malloc(sizeof(int*)*5);
int i,j;

对于(i=0;i,在OP给出的示例中,将数组放在堆栈上是最容易的

#包括stdio.h

void retArr(a[][3]) {
  a[0][0] = 1; a[0][1] = 2; a[0][2] = 3;
  a[1][0] = 4; a[1][1] = 5; a[1][2] = 6;
  a[2][0] = 7; a[2][1] = 8; a[2][2] = 9;
}

main() {
  int a[3][3];
  retArr(a);
}

是的,这不会使用return函数“返回”数组,但我想这不是问题的目的。数组a[][]确实会被加载,加载的a[][]在retArr()之后在main中可用调用时,不会覆盖任何内容。

请说明您遇到的错误类型。您需要完全避免这种错误。您返回的是一个在离开作用域时未定义的本地堆栈变量的地址。指针不兼容只是伤口上的盐。出于兴趣,为什么要从函数返回2D数组?这里有could是这样做的一个很好的理由,但很可能不是这样做的……至少有两个原因是错误的:返回类型是
int(*)[3]
,而不是
int**
,并且当函数返回时数组就不存在了,所以指针值无效。@JohnBode:int**没有错,只是类型不太强。(但返回指向堆栈变量的指针肯定是错误的。)好吧,这就是为什么我贴出帖子问他遇到了什么样的错误。我发现了编译错误;我的答案是正确的。我还想说,在函数签名中处理指针比处理数组更好,但我明天会扩展这个,将指针指向包含9
int
的内存区域,并假装它是正确的包含指向<代码> int >代码>的指针是非常不正确的。当数组较大时使用什么?例如,我需要双数组的44 K x 2。@ sGuangiaGa考虑通过参数传递一个结构或数组的引用,而不是返回一个值。如您可能猜到的,一个大的值能够耗尽(剩余的)。堆栈存储。在某些情况下,可以选择返回堆分配的结构或数组。不要在C中强制转换
malloc
的结果。该函数返回指向包含9
int
的内存区域的指针。假装它包含指向
int
的指针是非常不正确的,并且
return arr;
#include<stdio.h>
#include<stdlib.h>
int **return_arr()
{
    int **arr=(int **)malloc(sizeof(int *)*5);
    int i,j;
    for(i=0;i<5;i++)//checking purpose
    {
        arr[i]=(int *)malloc(sizeof(int)*5);
        for(j=0;j<5;j++)
        {
            arr[i][j]=i*10+j;
        }
    }
    return arr;
}
int main()
{
    int **now;
    now=return_arr();
    int i,j;
    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            printf("%d ",now[i][j]);
        }
        printf("\n");
    }
    return 0;
}
void retArr(a[][3]) {
  a[0][0] = 1; a[0][1] = 2; a[0][2] = 3;
  a[1][0] = 4; a[1][1] = 5; a[1][2] = 6;
  a[2][0] = 7; a[2][1] = 8; a[2][2] = 9;
}

main() {
  int a[3][3];
  retArr(a);
}