Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pointers pointing to array of integers

Here,I have some Doubt with the output.

Why the Output is same ?

   int (*r)[10];
   printf("r=%p  *r=%p\n",r,*r);
   return 0;

Platform- GCC UBUNTU 10.04

like image 326
Anil Arya Avatar asked Dec 20 '11 12:12

Anil Arya


3 Answers

Because Name of the array decays to an pointer to its first element.

   int (*r)[10]; 

Is an pointer to an array of 10 integers.
r gives you the pointer itself.

This pointer to the array must be dereferenced to access the value of each element.
So contrary to what you think **r and not *r gives you access to the first element in the array.
*r gives you address of the first element in the array of integers, which is same as r

Important to note here that:
Arrays are not pointers

But expressions involving array name sometimes behave as pointer when those being used as name of the array would not make sense.

like image 112
Alok Save Avatar answered Oct 01 '22 08:10

Alok Save


You would better understand if you look at the following program.

#include <stdio.h>

int main()
{
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int (*r)[10] = &a;

    printf("r=%p  *r=%p  *(r+0)=%p  *(r+1)=%p\n", r, *r, *(r+0), *(r+1));
    printf("sizeof(int)=%d \n", sizeof(int));

    return 0;
}

The output is as follows:

r=0xbfeaa4b4  *r=0xbfeaa4b4  *(r+0)=0xbfeaa4b4  *(r+1)=0xbfeaa4dc
sizeof(int)=4 

Observations / Point(s)-to-note:

  • _DO_NOT_ de-reference a pointer which has not yet made to point to an address. So in your program int (*r)[10]; was de-referenced without being assigned to a memory area. This is not acceptable.

  • If you see the output - *r is same as *(r+0) which is same as r (only w.r.t this case)

  • If you see the output for *(r+0) and *(r+1) it is 40 bytes (0xbfeaa4dc - 0xbfeaa4b4 = sizeof(int) * size of the array (which is 10 in this case). So when you increment a pointer to a particular type, it gets incremented to sizeof(type) bytes!

  • the other worth-notable points about a pointer-to-an-array-of-integers are explained here

Hope this helps!

like image 37
Sangeeth Saravanaraj Avatar answered Oct 01 '22 08:10

Sangeeth Saravanaraj


Remember that when an expression of type "N-element array of T" appears in most contexts, it will be converted to an expression of type "pointer to T" and its value will be the address of the first element in the array. The exceptions to this rule are when the array expression is an operand of either the sizeof or unary & (address-of) operands, or if the array expression is a string literal being used as an initializer in an array declaration.

Your situation is a mirror image of the following:

int a[10] = {0};
printf("a = %p, &a = %p\n", (void *) a, (void *) &a);

In the printf call, the expression a has its type converted from "10-element array of int" to "pointer to int" based on the rule above, and its value will be the address of the first element (&a[0]). The expression &a has type "pointer to 10-element array of int", and its value will be the same as a (the address of the first element in the array is the same as the address of the array itself).

Your code has a bit of undefined behavior in that you're dereferencing r before it has been assigned to point anywhere meaningful, so you can't trust that the output is at all accurate. We can fix that like so:

int a[10] = {0};
int (*r)[10] = &a;
printf("r = %p, *r = %p\n", (void *) r, (void *) *r);

In this case, r == &a and *r == a.

The expression r has type "pointer to 10-element array of int", and its value is the address of a. The expression *r has type "10-element array of int, which is converted to "pointer to int", and its value is set to the address of the first element, which in this case is a[0]. Again, the values of the two expressions are the same.

like image 41
John Bode Avatar answered Oct 01 '22 07:10

John Bode