Изменить массив внутри нескольких функций с помощью указателей - PullRequest
0 голосов
/ 29 сентября 2018

У меня следующий код, и я хочу изменить массив, переданный через несколько функций, например:

int main(void)
{
    int *arr, n;

    scanf("%d", &n);
    arr = (int*)malloc(n*sizeof(int));
    for (i = 0; i < n; i++)
    //scanning into array

    func1(arr, n);
}

Теперь я хочу, чтобы каждый цикл изменял массив, а затем использовал измененный массивв следующем цикле и т. д.

void func1(int *x, int h)
{
    for (int i = 1; i < height; i++)
        change(&x, h, i);
}

Здесь мне нужно изменить исходный массив, чтобы он был таким же, как gArr или иметь те же значения

void change(int **x, int h, int i) {


    int *gArr = (int*)malloc(h*sizeof(int));
    //doing some operations


    //here I want to somehow change the original array to be gArr 
    //or to have the same values as gArr
    *x = gArr;
}

Я пробовал несколько подходов, и я почему-то не могу получить правильный результат, спасибо за помощь.

Ответы [ 4 ]

0 голосов
/ 29 сентября 2018

Я как-то понял это так:

void func1(int *x, int h)
    {
        for (int i = 1; i < height; i++)
            change(x, h, i);
    }


void change(int *x, int h, int i) {

    int *gArr = (int*)malloc(h*sizeof(int));
     //doing some operations

    memcpy(x, gArr, h*sizeof(int));
    free(gArr);
}

memcpy сделал работу, но я не уверен, что это правильный подход.

0 голосов
/ 29 сентября 2018

Необходимо различать указатель на массив и элементы этого массива.Давайте сначала пройдемся по тому, что вы делаете прямо сейчас:

int main(void)
{
    int *arr, n;

    scanf("%d", &n);
    arr = (int*)malloc(n*sizeof(int));
    // ...
    func1(arr, n);
}

int *arr объявляет указатель на int в области действия функции main().Через какой-то указатель вы передаете этот указатель в функцию func1.Теперь C является языком передачи по значению, это означает, что func1 получает значение arr, и это значение является адресом вашего динамически распределяемого массива.Это позволяет вам манипулировать элементами, на которые указывает arr, но не самим arr.Так что если внутри func1 у вас есть:

void func1(int *arr, int n) {
   arr = dynamic_pointer_to_another_array();
}

, то изменится только arr внутри func1, но не тот, что в main.Теперь вы частично это поняли, потому что ваша change() функция вместо этого принимает указатель на указатель, однако в func1() вы имеете:

change(&arr, h, i);

Вы можете подумать, что & здесь передаетадрес arr из main, но на самом деле он передает адрес arr из func1, потому что еще раз C является передачей по значению языка.Каждый раз, когда вы передаете значение функции, оно копируется в область действия этой функции, и любые операции над значением не будут отражаться в вызывающей стороне.

Простое решение этого - изменить func1 навозьмите int **arr вместо int *arr, таким образом, вы можете сделать:

change(arr, h, 1);

и внутри change вы можете сделать:

*arr = new_array();

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

Важное примечание

В вашем коде есть еще один огромныйпроблема.Вы динамически выделяете массив, а затем пытаетесь переназначить указатель на этот массив другому массиву.Это, безусловно, приведет к утечкам памяти и висящим указателям.Выполнение

int *arr = malloc(sizeof(int) * N);
arr = new_array();

гарантированно приведет к утечкам памяти, поскольку вы никогда не используете free для этого указателя для освобождения памяти, а после переназначения ее другому массиву вы теряете все ссылки на него.У вас есть несколько вариантов, как это сделать.Если вам нужно увеличить размер arr, тогда вы используете realloc вместо выделения нового массива.Таким образом, вам все равно придется только free один раз.

0 голосов
/ 29 сентября 2018

Таким образом, проблема в том, что изменение значения внутри адреса не влияет правильно, HOW COULD IT BE UPDATED, когда вы имеете дело с копией массива, созданного вами в main.

Я видел, что вы использовали тип int ** в списке параметров функции change(int**, int, int).И причина использовать это, потому что изменение может вступить в силу на переданном массиве правильно!

Таким же образом, вы должны также использовать int ** внутри, как этот func1 (int **), чтобы операция могла отражать исходную.

0 голосов
/ 29 сентября 2018

Ваш график вызовов:

main(void)
    func1(int *x)
        change(int **x)

, поэтому, если вы передадите переменную-указатель от main через func1 до change, а затем измените переменную (т. Е. Место в памяти, на которое указывает), затем вы также должны передать его адрес func1, иначе main никогда не сможет наблюдать изменения:

main(void)
    func1(int **x)
        change(int **x)

... и не забудьте free исходный массив в change.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...