Jai Yadav
Jai Yadav

Reputation: 13

How exactly pointer to an array works?

Can anyone explain how these values will be printed and why p and *p are returning the same values.

#include <stdio.h>

int main(){
    int arr[] = {1,2,3,4};
    int (*p)[4];

    p = &arr;

    printf("%u %u %u %u %u", arr, &p, p, *p, **p);
    p++;
    printf("\n%u %u %u %u %u", arr, &p, p, *p, **p);

    return 0;
}

outputs on my machine are as follows:

2686768 2686764 2686768 2686768 1

2686768 2686764 2686784 2686784 2686792

Upvotes: 0

Views: 141

Answers (2)

Ely
Ely

Reputation: 11162

Your example is messy, but pointer arithmetic is messy in general, disrespectful to types. Your example does not make sense from a type theory point of view.

arr points to the first element of the array. Note that arr[i] is equivalent to *(arr+i). arr is a 4-elements array of type int.

p is a pointer to a 4-element array of type int.

You assign to p the address of &arr, which has the same address as arr (but the type is different, see below).

Then you print it out and this means:

  • arr is the address of the first element of the array
  • &p is the address of p
  • p is the address of &arr (whole array), which is the address of arr, which is the address of the first element in the array
  • *p is the address of arr, which is the address of the first element in the array
  • **p is trying to dereference *p, which is dereferencing arr, which actually is the first element of the array

After you increment p++: arr and &p don't change, the rest does


From the C Book

We have already emphasized that in most cases, the name of an array is converted into the address of its first element; one notable exception being when it is the operand of sizeof, which is essential if the stuff to do with malloc is to work. Another case is when an array name is the operand of the & address-of operator. Here, it is converted into the address of the whole array. What's the difference? Even if you think that addresses would be in some way ‘the same’, the critical difference is that they have different types. For an array of n elements of type T, then the address of the first element has type ‘pointer to T’; the address of the whole array has type ‘pointer to array of n elements of type T’; clearly very different. Here's an example of it:

int ar[10];
int *ip;
int (*ar10i)[10];       /* pointer to array of 10 ints */

ip = ar;                /* address of first element */
ip = &ar[0];            /* address of first element */
ar10i = &ar;            /* address of whole array */

Upvotes: 1

Lundin
Lundin

Reputation: 213862

printf("%u %u %u %u %u", arr, &p, p, *p, **p);

  • arr is the array itself. When the array name is used in an expression like this, it decays to a pointer to the first element, so you get the address of that element.
  • &p is the address where the array pointer is stored. The only reason why you see this as the same address as the others is because you are running optimized code. Disable optimizations or declare p as static volatile and you'll see a change.
  • p is the address of the array, which will of course be the same as the address of the first element.
  • *p gives you an array type, which then decays into a pointer to the first element. This is identical to arr.
  • **p gives you the contents of the first element in the array.

p++ will increase the pointer by the rules of pointer arithmetic. Thus the address that p points at will be increased by the size of what it points at, which is an array of 4 ints, each 4 bytes large (assuming 32 bit). Therefore p will now point outside valid memory and anything will happen if you try to access it.

Upvotes: 1

Related Questions