Как я могу написать функцию для копирования массива элементов для определенного количества элементов для копирования - PullRequest
1 голос
/ 19 июня 2019

Я пытаюсь узнать, как использовать указатели, и хочу написать функцию, в которой у меня есть два массива целых чисел, и я хочу скопировать массив целых чисел для определенного числа (nbr) целых чисел для копирования.

int A[]= {1,2,3,4};
int B[] = {6,7,8,9};

int main(void)
{
    int_copy(&A, &B, 3);
}

void int_copy(int *ptrA, int *ptrB, int nbr)
{
    int * p = ptrA;
    for (int i = 0; i<nbr; i++)
    {
        *ptrA++ = *ptrB++;
    }

    printf("%d\n", *ptrA);
    printf("%d\n", *ptrB);

    return;
}

Я хочу вывести 6,7,8,4 для массива A, но я получаю следующие сообщения об ошибках:

intcopy.c:10:14: warning: incompatible pointer types passing 'int (*)[4]' to parameter of type 'int *' [-Wincompatible-pointer-types]
    int_copy(&A, &B, 3);
             ^~

intcopy.c:6:20: note: passing argument to parameter 'ptrA' here
void int_copy(int *ptrA, int *ptrB, int nbr);
                   ^

intcopy.c:10:18: warning: incompatible pointer types passing 'int (*)[4]' to parameter of type 'int *' [-Wincompatible-pointer-types]
    int_copy(&A, &B, 3);
                 ^~

intcopy.c:6:31: note: passing argument to parameter 'ptrB' here
void int_copy(int *ptrA, int *ptrB, int nbr);
                              ^

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Вот некоторые проблемы в вашем коде:

  • Вы должны определить или хотя бы объявить функцию int_copy перед ее вызовом.

  • Вы должны передать указатели на содержимое массива на int_copy, что делается путем передачи указателей на первые элементы массивов: int_copy(&A[0], &B[0], 3);, которые можно упростить до int_copy(A, B, 3);

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

Вот исправленная версия:

int A[] = { 1, 2, 3, 4 };
int B[] = { 6, 7, 8, 9 };

void int_copy(int *ptrA, int *ptrB, int nbr) {
    for (int i = 0; i < nbr; i++) {
        *ptrA++ = *ptrB++;
    }
}

void int_print(const char *msg, const int *p, int nbr) {
    printf("%s:", msg);
    for (int i = 0; i < nbr; i++) {
        printf(" %d", p[i]);
    }
    printf("\n");
}

int main(void) {
    int_print("before copy", A, 4);
    int_copy(A, B, 3);
    int_print("after copy", A, 4);
    return 0;
}
1 голос
/ 19 июня 2019

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

int_copy(A, B, 3);

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

int(*pointer)[4] = &A;

Синтаксис ужасен, я знаю ...

Я хочу вывести 6,7,8,4 для массива A

Предположим, поэтому вы сначала взяли резервную копию ptrA? Исключительно, вы не используете это ...

printf("%d\n", *ptrA);
printf("%d\n", *ptrB);

Эти два оператора будут печатать только одно целое число, на которое указывают два указателя. Когда вы продвинете их обоих на 3 уже в цикле, они будут распечатаны 4 и 9.

Вам потребуется использовать указатель резервной копии p и выполнить итерацию в другом цикле ровно по четырем элементам. Исключительно: ваша функция копирования не может знать о количестве элементов массива. Печать таким способом возможна при некоторых ограничениях, но это опасный код. Представьте, что произошло, если вы передали указатель куда-то посередине массива (-> неопределенное поведение из-за чтения за пределами массива!).

Безопасным способом было бы не печатать в вызываемой функции, а:

int main(void)
{
    int_copy(&A, &B, 3);
    for(size_t i = 0; i < sizeof(A)/sizeof(*A); ++i)
        printf("%d ", A[i]);
}

Наконец: вам не нужно явно return в void-функциях (только если вы хотите преждевременно завершить работу ...).

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