1

Im trying to learn how to use pointers and want to write a function where I have two arrays of integers and want to copy an array of integers for a specific number(nbr) of integers to copy.

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;
}

I want to output 6,7,8,4 for array A, but i get the following error messages:

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);
                              ^
4
  • try: int_copy(&A[0], &B[0], 3); Commented Jun 19, 2019 at 18:21
  • ...or int_copy(A, B, 3); Commented Jun 19, 2019 at 18:21
  • Yep, A is a pointer to int, &A is a pointer to array of 4 ints. Commented Jun 19, 2019 at 18:27
  • 1
    @LeeDanielCrocker Actually, A is an array of four ints; it decays to a pointer when used in a context where a pointer is required... Commented Jun 19, 2019 at 18:31

2 Answers 2

1

The point is: arrays decay to pointers to their first element automatically, if passed to functions. So you just call your function like

int_copy(A, B, 3);

Taking the address of an array is possible, and as arrays and their first element always share the same address, will yield the same numerical value. but the type of pointer differs, it won't be a pointer to int, it will be a pointer to int-array of length 4:

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

Syntax is ugly, I know...

I want to output 6,7,8,4 for array A

Suppose that's why you took a backup copy of ptrA first? Solely, you don't use it...

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

These two statements will only print one single integer each, the ones the two pointers point to. As you advanced both of them by 3 already in your loop, they will print out 4 and 9.

You'd need to use your backup pointer p and iterate in another loop over exactly four elements. Solely: your copy function cannot know about how many array elements there are. Printing this way might be possible under some constraints, but it is dangerous code. Imagine what happened if you passed a pointer to somewhere in the middle of the array (-> undefined behaviour due to reading beyond array bounds!).

The safe way would be not to print in the called function, but rather:

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

Finally: you don't need to explicitly return in void functions (only if you want to exit prematurely...).

Sign up to request clarification or add additional context in comments.

4 Comments

I made the changes and it worked, but im a little confused with ``` i < sizeof(A)/sizeof(*A);` ``` why are you dividing sizeof(A) with sizeof(*A)
@bman sizeof(whatever) gives you the size of the object in question, whatever it is (struct, array, pointer, ...), in bytes – but you want to get the number of elements. So for arrays you divide the total size in bytes by the number of bytes of one single element. In your concrete case, assuming int having four bytes (this is not necessarily the case!): sizeof(A) is 16, sizeof(*A) is the size of A's first element, i. e. an int, i. e. 4, so final result is 16/4 == 4. Some prefer the variant sizeof(A)/sizeof(A[0]), but that's equivalent...
In the line for(size_t i = 0; i < sizeof(A)/sizeof(*A); ++i) I changed i < sizeof(A) to i < sizeof(&A) and it now only printed the first two integers. Does using & before A make it 8 bytes?
No, it doesn't change A at all. &A produces a pointer (have a look at my answer again for exact type...), so you get the size of a pointer (as if you did sizeof(void*)), which obviously is eight bytes on your system (again this can differ...). And can differ by far from the size of the original array...
1

Here are some problems in your code:

  • you should define or at least declare function int_copy before calling it.

  • You should pass pointers to the array contents to int_copy, which is done by passing pointers to the first elements of the arrays: int_copy(&A[0], &B[0], 3); which can be simplified as int_copy(A, B, 3);

  • In int_copy, you increment both pointers in the loop, which is fine, but you should not try and access the element they point to at the end of the loop as the point just past the end of the arrays, so reading these values has undefined behavior.

Here is a corrected version:

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;
}

2 Comments

RE the last bullet point: in this case, OP passes nbr = 3 and the array length is 4 so the printf statements are ok.
In void print for const int *p / when you call int print in main and have A in the position of const int *p, is p now pointing to the array A

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.