Возврат динамического массива через функцию void в C

В моей программе на C я использую функцию void со следующими аргументами: один двумерный массив int, один указатель int, который будет использоваться для создания нового динамического массива, и последний указатель int, который будет содержать количество счетчиков, которые будут происходить внутри функция. Таким образом, динамический массив создается в функции с использованием malloc, и все работает нормально, пока я не напечатаю его элементы в main () после вызова функции. Я получаю ерунду вместо цифр, которые я должен видеть. Вот код функции:

void availableMoves(int array[][3], int *av, int *counter)
{
    int i, j;
    for (i=0; i<3; i++)
    {
        for (j=0; j<3; j++)
        {
            if (array[i][j] == E)
            {
                printf("%d ", 3*i + j + 1);
                (*counter)++;
            }
        }
    }
    av = (int *) malloc(*counter * sizeof(int));
    if (av == NULL)
    {
        printf("ERROR!");
    }
    else
    {
        for (i=0; i<*counter; i++)
            *(av + i) = 0;
        int pos = 0;
        for (i=0; i<3; i++)
        {
            for (j=0; j<3; j++)
            {
                if (array[i][j] == E)
                {
                    *(av + pos++) = 3*i + j + 1;
                }
            }
        }
    }
}

person sotirelisc    schedule 02.01.2013    source источник
comment
Просто комментирую код: поскольку у вас есть случай ошибки, вам не следует изменять *counter таким образом в случае ошибки. Используйте временную int tmp_count = *counter; переменную и присвойте ее обратно *counter, только если функция завершилась успешно. Или сделайте это abort();, если malloc не работает, или что-то в этом роде. Избегайте получения частичного результата (av=null, но *counter все еще изменен).   -  person hyde    schedule 02.01.2013
comment
Попытайтесь понять разыменование указателей и индексацию. *(av + pos++) = 3*i + j + 1; то же самое, что и av[pos++] = 3*i + j + 1;, но большинство читателей предпочитают вторую форму. Аналогично (*counter)++;, которое можно было бы записать как *counter += 1;, избегая скобок.   -  person wildplasser    schedule 02.01.2013
comment
@hyde: Ты прав, но это была быстрая проверка malloc, я еще не закончил. :)   -  person sotirelisc    schedule 02.01.2013
comment
@wildplasser: Что-то не так со скобками?   -  person sotirelisc    schedule 02.01.2013
comment
Нет, с ними все в порядке. Но большинство людей склонны сокращать количество скобок просто потому, что их легче читать с меньшим количеством ((.) (.)).   -  person wildplasser    schedule 02.01.2013


Ответы (2)


В этой функции av - указатель, переданный копией. Поэтому, когда вы изменяете значение указателя внутри функции, исходный указатель не будет изменен.

Есть две возможности:

  • использовать указатель на указатель (int **av);
  • вернуть выделенный указатель (return av).

Так что либо:

void availableMoves(int array[][3], int **av, int *counter);

Or:

int *availableMoves(int array[][3], int *av, int *counter)

И звонок:

availableMoves(array, &av, &counter);
av = availableMoves(array, av, &counter);
person md5    schedule 02.01.2013
comment
Третий (наиболее последовательный ИМО) подход - вернуть логическое значение: вернуть истину, если и av, и counter были успешно изменены, в противном случае вернуть ложь и оставить av и counter без изменений. - person hyde; 02.01.2013
comment
@hyde: В противном случае было бы неплохо использовать возвращаемое значение. - person md5; 02.01.2013
comment
Решил использовать первый подход и вроде работает! Спасибо! - person sotirelisc; 02.01.2013

используйте двойной указатель для динамического массива int **av вместо int *av

void availableMoves(int array[][3], int **av, int *counter)

и в функции измените av на *av

person MOHAMED    schedule 02.01.2013