Возврат двумерного массива или указателя на него - PullRequest
3 голосов
/ 31 марта 2011

Если в функции создается 2d-массив int 2DRepresentation[mapWidth][mapHeight];, каков наилучший способ вернуть это?

как выглядит возвращаемая функция?

Было бы предпочтительнеесоздать указатель на 2d массив и передать его в функцию, изменив его внутри функции?Если да, то как выглядит указатель на двумерный массив?Вот так:

int *2DRepresentation[mapWidth][mapHeight];?

Как будет выглядеть параметр функции, который принимает указатель 2d-массива?

Ответы [ 4 ]

2 голосов
/ 31 марта 2011

Вам нужно будет вернуть базовый адрес массива, т.е. Pointer. Однако единственное решение состоит в том, что вам придется сделать массив static, иначе, как только функция выйдет из области видимости, она будет уничтожена. Если вы не хотите делать это static, вы должны использовать dynamic memory allocation.

Пример псевдокода:

    int **array; // array is a pointer-to-pointer-to-int
    array = malloc(mapHeight * sizeof(int *));
    if(array == NULL)
        {
        fprintf(stderr, "out of memory\n");
        exit or return
        }
    for(i = 0; i < mapHeight ; i++)
        {
        array[i] = malloc(mapWidth * sizeof(int));
        if(array[i] == NULL)
            {
            fprintf(stderr, "out of memory\n");
            exit or return
            }
        }

Вот как вы можете передать его в функцию с именем foo скажем:

foo(int **array, int _mapHeight, int _mapWidth)
    {
    }

Массивы распадаются на указатели, поэтому вам нужно передавать строки и значения столбцов как отдельные аргументы.

2 голосов
/ 31 марта 2011

Если создан 2d массив "int 2DRepresentation [mapWidth] [mapHeight];"как лучше вернуть эту функцию внутри функции?

Если она создается внутри функции так, как вы ее представляли (предполагая, что mapWidth, mapHeight являются константами), ее возвращать не следует.Поскольку он находится в стеке , а выходит из области действия при возврате функции и возвращение ссылки на нее просто указывает на мусор.


Будетпредпочтительнее создать указатель на двумерный массив и передать его в функцию, модифицируя ее внутри функции?

Да, вы правы.

какбудет выглядеть параметр функции, который принимает указатель массива 2d?

Пример:

void foo( int twoDimensionalArray [][3] )
{

    // Now you can modify the array received.

}

int main()
{
     int ar[3][3] ;
     foo(ar) ;
     // .....
}

Или вы можете динамически распределять память в стороне foo и возвращать ссылку на нее.

int** foo()
{
    // ....
    return mallocatedTwoDimensionalArray ;
}
1 голос
/ 01 апреля 2011

Чтобы массив сохранялся в памяти, его необходимо либо объявить static, либо его следует явно выделить с помощью malloc или calloc (каждое решение имеет функциональные последствия - то есть версия static будет перезаписать при следующем вызове функции, и выделенная версия должна быть явно освобождена позже, чтобы избежать утечек памяти).

Обратите внимание, что указатели и массивы - это не одно и то же в C, и, поскольку вы имеете дело с динамическим размещением в случае malloc, вы будете работать с указателями. Ссылка на элементы массива с использованием этих указателей будет функционально такой же, как ссылка на элементы массива, поэтому вы не должны заметить разницы после создания массива.

Вот пример, который выделяет, заполняет и возвращает двумерный массив, используя один malloc (как для эффективности, так и для разрешения использования одного free для освобождения):

int **get2dArray(int rows, int cols)
{
    int **array2d;
    int i, j, offset;
    int *gridstart;

    offset = rows * sizeof(int *);

    array2d = malloc( offset + rows*cols*sizeof(int) );

    /* Demote to char for safe pointer arithmetic */
    gridstart = (int *)((char *)array2d + offset); 

    for ( i = 0; i < rows; i++ ) {
        /* Point to the proper row */
        array2d[i] = gridstart + i*cols;

        /* Populate the array -- your code goes here */
        for ( j = 0; j < cols; j++ ) {
            array2d[i][j] = i*cols + j;
        }
    }

    return array2d;
}


int main ( int argc, char **argv )
{
   int **testarray;

   testarray = get2dArray( 10, 100 );

   /* Verify that addressing and population went as planned */
   printf( "%d %d %d %d %d %d\n", testarray[0][0], testarray[2][55], 
           testarray[4][98], testarray[5][0], testarray[7][15], 
           testarray[9][99] );   

   free(testarray);

   return 0;
}

Есть много других способов сделать это, но это демонстрирует функцию, которая возвращает двумерный указатель "массив".

1 голос
/ 01 апреля 2011

Лучше определить массив вне функции и передать его внутрь.

Помните, что при использовании в качестве аргумента функции массив превращается в указатель на свой первый элемент и, следовательно, внутри функции, это указатель и не имеет информации о первоначальном размере.Вы также должны передать размер.
Если у вас есть компилятор C99, вы можете использовать «изменяемый параметр» (см. 6.7.5.3):

int func(int rows, int cols, int data[rows][cols]) {
    int sum = 0;
    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
            sum += data[row][col];
        }
    }
    return sum;
}

и вызывать его, например:

int main(void) {
    int a[42][100] = {0};
    if (func(42, 100, a) == 0) /*ok*/;

    int b[1000][2] = {0};
    if (func(1000, 2, b) == 0) /*ok*/;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...