我的阵列是什么类型的?

时间:2014-04-06 09:37:45

标签: c arrays types

我有以下功能:

int** myfunc() {
   int array[2][2];

   // operation on the array

   return array;
}

编译器出现以下错误:

 cannot convert 'int (*)[2]' to 'int**' in return

所以我的问题是:如何返回我的数组?

4 个答案:

答案 0 :(得分:4)

  

所以我的问题是:如何返回我的数组?

你做不到。名为array的数组具有函数范围,并且在函数myfunc返回时超出范围。这意味着该数组不再存在,并且尝试访问它将调用未定义的行为。此外,myfunc的返回类型为int **。在退货声明中

 return array;

名为array的数组被隐式转换为指向其元素的指针。 int array[2][2];array定义为包含int[2]类型的2个元素的数组,即2个整数的数组。因此,array语句中的return被隐式转换为类型int (*)[2],即指向2个整数数组的指针。这解释了错误消息。

如果你想从一个函数返回一个数组,你应该使用malloc动态分配它,以后应该在调用者使用后释放它。

// you should change function signature to take the array size.
// and change return type to (int *) to return a pointer to the
// first element of the dynamically allocated array 
int *myfunc(int len) {
   int *array = malloc(len * sizeof *array);
   if(array == NULL) {
       printf("error in memory allocation\n");
       return NULL;
       // handle it
   }

   // operation on the array

   return array;
}

请注意,数组类型对象是一个连续分配的非空对象集,具有特定的成员对象类型,称为元素类型。因此,二维数组不是新类型。它只是一种数组类型,其中数组的元素本身就是数组。这意味着我们有以下等价 -

// an automatic array of 200 elements allocated on the stack
int auto_array[10][20]; 

// a dynamic array of 200 elements allocated on the heap
int *dynamic_array = malloc((10 * 20) * sizeof *array); 

printf("%d\n", auto_array[4][8];)  // prints element in the 5th row, 9th column
printf("%d\n", dynamic_array[4*10 + 8]);  // prints element in the 5th row, 9th column

答案 1 :(得分:1)

这只能修复编译器错误

编译器已经为您提供了正确的返回类型,您只需要为该类型指定一个名称即可轻松返回:

typedef int (*myArrayPtr)[2];

myArrayPtr myFunc() {
    int foo[2][2];
    return foo;    //Compiles, BUT DON'T USE IT (see below)
}

或者,您可以像这样编写函数声明(但请不要,这应该只在尝试赢得国际混淆C代码竞赛的代码中完成):

int (*myFunc())[2] {
    int foo[2][2];
    return foo;    //Compiles, BUT DON'T USE IT (see below)
}

此方法确实有效

上面的代码返回一个指向局部变量的指针,该变量在myFunc()返回时自动释放。如果调用函数以任何方式使用返回的指针,则可能发生任何事情。要正确返回2D数组,您需要malloc()

typedef int myArray[2];

myArray* myFunc() {
    myArray* foo = malloc(2*sizeof(*foo));
    foo[1][1] = 7;
    return foo;
}

注意,两个维度中的一个以数组类型编码,而另一个维度隐含在指针中。这就是为什么sizeof *foo必须乘以第一维的大小。当然,您也可以在数组类型中对这两个维度进行编码,但这需要您在访问其元素时编写其他取消引用:

typedef int myArray[2][2];

myArray* myFunc() {
    myArray* foo = malloc(sizeof(*foo));
    (*foo)[1][1] = 7;
    return foo;
}

答案 2 :(得分:0)

阵列和指针,虽然看似相似,但在C中并不是一回事。

您正在尝试返回一个局部变量,其内存在堆栈上分配。一旦函数退出,局部变量将从堆栈中弹出,这就是为什么大多数编译器在您尝试返回局部变量的地址时会给出警告的原因。返回的地址指向一个已消失的值。

你需要做的是声明一个int **&把它返还。您可以使用malloc.h头中存在的malloc()动态分配内存。以下内容应该有效。

#include <stdio.h>
#include <malloc.h>

int** myfunc()
{
    // Allocate memory so array can hold two int *
    int** array = malloc(sizeof(int *) * 2);

    // Allocate memory for each of the pointers that the array holds
    // We want to reserve space for two integers in each slot.
    array[0] = malloc(sizeof(int) * 2);
    array[1] = malloc(sizeof(int) * 2);

    array[0][0] = 0;
    array[0][1] = 1;
    array[1][0] = 2;
    array[1][1] = 3;

    return array;
}

int main(void)
{
    int i, j;
    int **x;
    x = myfunc();

    for (i = 0; i < 2; ++i) {
        for (j = 0; j < 2; ++j) {
            printf("%d", x[i][j]);
        }
    }

    return 0;
}

当你完成它时,不要忘记free()数组的内容。

答案 3 :(得分:0)

数组中的数组不是第一类数据类型,不能通过复制返回数组,并且返回对局部变量的引用将具有未定义的行为(并且永远不会好)。

有三种方法(至少)可以做你正在尝试的事情。最常见的(更不用说安全和高效)是让调用者拥有数组,然后通过引用将数组传递给函数并让函数在提供数组:

void myFunc( int array[2][2] )
{
    // operate directly on caller's array
}

第二种方法是将数组包装在struct中,该struct是一类数据类型,可以通过复制或引用进行交换。注意对于大型结构,通过复制进行交换可能会在计算上变得昂贵。

typedef struct
{
    int array[2][2] ;
} array_container ;

array_container myFunc()
{
    array_container contained_array ;

    return contained_array ;
}

在函数内动态分配数组是可能的,但是留下了谁负责释放内存以及如何以及何时安全执行此操作的问题。但是,虽然我不推荐它:

#define ARRAY_DIM1 2
#define ARRAY_DIM2 2

int** myfunc()
{
    int** array = malloc( sizeof(int*) * ARRAY_DIM1 ) ;
    int* array_memory = malloc( sizeof(int) * ARRAY_DIM1 * ARRAY_DIM2 ) ;
    int i = 0 ;

    for( i = 0; i < ARRAY_DIM1; i++ )
    {
        array[i] = array_memory[i * ARRAY_DIM2]
    }

    return array;
}