Aneesh Dogra
Aneesh Dogra

Reputation: 740

Pointers to arrays in C

I just saw this code snippet Q4 here and was wondering if I understood this correctly.

#include <stdio.h>

int main(void)
{
   int a[5] = { 1, 2, 3, 4, 5 };
   int *ptr = (int*)(&a + 1);

   printf("%d %d\n", *(a + 1), *(ptr - 1));

   return 0;
}

Here's my explanation:

int a[5] = { 1, 2, 3, 4, 5 }; => a points to the first element of the array. In other words: a contains the address of the first element of the array.

int *ptr = (int*)(&a + 1); => Here &a will be a double pointer and point to the whole array. I visualize it like this: int b[1][5] = {1, 2, 3, 4, 5};, here b points to a row of a 2D array. &a + 1 should point to the next array of integers in the memory (non-existent) [kind of like, b + 1 points to the second (non-existent) row of a 2D array with 1 row]. We cast it as int *, so this should probably point to the first element of the next array (non-existent) in memory.

*(a + 1) => This one's easy. It just points to the second element of the array.

*(ptr - 1) => This one's tricky, and my explanation is probably flawed for this one. As ptr is an int *, this should point to int previous to that pointed by ptr. ptr points to the non-existent second array in memory. So, ptr - 1 should probably point to the last element of the first array (a[4]).

Upvotes: 8

Views: 1848

Answers (3)

Apriori
Apriori

Reputation: 2306

Your statement is essentially correct, and you probably understand it better than most professionals. But since you are seeking a critique, here is the long answer. Arrays and pointers in C are different types, this is one of the most subtle details in C. I remember one of my favorite professors saying once that the people who made the language latter regretted making this so subtle and often confusing.

It is true in many cases an array of a type, and a pointer to a type can be treated the same way. They both have a value equal to their address, but they are truly different types.

When you take the address of an array &a, you have a pointer to an array. When you say (a + 1) you have a pointer to an int, when you just say a you have an array (not a pointer). a[1] is exactly the same as typing *(a + 1), in fact you could type 1[a] and it would be exactly the same as the previous two. When you pass an array to a function, you are not really passing an array, you are passing a pointer void Fn(int b[]) and void Fn(int *b) are both the exact same function signature, if you take sizeof b within the function, in both cases you will get the size of a pointer.

Pointer arithmetic is tricky, it always offsets by the size of the object it's pointing to in bytes. Whenever you use the address of operator you get a pointer to the type you applied it to.

So for what's going on in your example above:

  • &a is a pointer to an array, and so when you add one to it, it is offset by the sizeof that array (5 * sizeof(int)).
  • When you cast to int*, the cast retains the value of the pointer, but now its type is pointer to int, you then store it in ptr, a variable of type pointer to int.
  • a is an array, not a pointer. So when you say a + 1 you apply the addition operator to an array, not a pointer; and this yields a pointer to one-past the first element of the type stored in the array, int. Dereferencing it with * gives you the int pointed to.
  • ptr is a pointer to int, and it points one past the end of the array. (it is legal by the way to point one past the end of an array, it's just not legal to dereference this pointer) When you subtract 1 from it, you end up with a pointer to an int that is the last in the array, which you can dereference. (Your explain of visualizing int b[1][5] = {1, 2, 3, 4, 5}; is something I've not heard before, and while I can't honestly say if this is technically correct, I will say this is how it works and I think this is a great way to think of it; I will likely do so in the back of my mind from now on.)

Types will get very tricky in C, and also in C++. The best is yet to come.

Upvotes: 1

Jeyaram
Jeyaram

Reputation: 9474

Here &a will be a double pointer.

No. It is a pointer to an array. In this example, int (*)[5]. Refer C pointer to array/array of pointers disambiguation

so when you increment pointer to an array, it will crosses the array and points to non-existent place.

In this example, It is assigned to integer pointer. so when int pointer is decremented, it will point to previous sizeof(int) bytes. so 5 is printed.

Upvotes: 6

Jayesh Bhoi
Jayesh Bhoi

Reputation: 25865

As per your explanation you understand array pointer correctly.Using statement

 int *ptr = (int*)(&a + 1);

you point to the next address of address occupied by whole array a[] so you can access the array element using ptr by decrementing address of ptr.

Upvotes: 1

Related Questions