Understanding and manipulating pointers to integer arrays

101 Views Asked by At

I am having troubles with the following code:

int a[] = {1, 2, 3, 4};
  
fprintf(stdout,
        "a      : %lu\n"
        "*a     : %d\n"
        "&a     : %ld\n"
        "**(&a) : %d\n",
        (unsigned long int)a,
        *a,
        (unsigned long int)&a,
        **(&a)
);

Output:

a      : 140726063647232
*a     : 1
&a     : 140726063647232
**(&a) : 1

i know that &a is a pointer to the 1 D array. And &a's type is int (*)[4]. I am confused with how comes **(&a): 1.

3

There are 3 best solutions below

0
On

Another way to look at it is through the resulting type after each address of or dereference operation. A basic rule for array access is Array-pointer conversion. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) which applies on access to any array (subject to the 4 exceptions listed [3 in the C18 standard -- _Alignofis no longer listed]).

The key is to understand that an array, on access, is converted to a pointer to the first element (subject to limited exception - not relevant here). If you take the address of an array, the address is the same as that of the first element, but the type of pointer is completely different.

     a   - pointer to int
    &a   - pointer-to-array int[4], proper type: int (*)[4]

When you dereference a, you get the first element:

    *a   - int

Why? *a is short for the full derefernce operation with an offset of 0, e.g. *(a + 0) which is equivalent to a[0] in index notation.

When you dereference your pointer-to-array int[4], you get your array back:

 *(&a)   - int[4] -> converted to pointer to first element.

which then, by operation of, 6.3.2.1(p3) is converted to a pointer to the first element. Dereference again and you get the first element:

**(&a)   - int

It's worth learning now as it will save you a lot of bewilderment later.

0
On

&a is a pointer to an array. *p gets what the pointer points to, so *&a gets the array, a.

An array treated as a pointer degenerates into a pointer to its first element, so *a is 1.

Since *&a is just a, **&a is the same as *a, which is 1.

0
On
  1. if you whish to print an address yous hould use the %p conversion specifier for the printf or fprintf function.
  2. on the other hand, printing integer data type with the same functions above, you should use the %d conversion specifier. then you can omit all the up-cast to unsigned long int data type.
  3. c arrays decays to pointer of the same data type in your case (not in all cases arrays can decays to pointer). in your prints you have used this fact, e.g when dereference the array *a. this fact in c enable us to writhe the folowing statement: int* a_ptr = a; AND int* ptr = &a[0];. now a_ptr and ptr are equal! pointing to the same address in memory.
  4. printing a is like printing the a_ptr value and like printing the ptr value. which ends in printing the &a[0].
  5. printing *a is like printing *a_ptr and like printing *ptr and since ptr = &a[0]; then , *ptr == *&a[0]==a[0] so in simple words its a[0] which is 1.
  6. priniting &a. now what is &a ? its a pointer to array of integeres! and to be more precised its a pointer to array of 4 integeres, which is int (*)[4] so when printing the address of a its like printing the dereference of *(int (*)[4]) which is the the address of the array simple a. be aware that the data types are comletley different! a and &a!
  7. printing **(&a) is the same as *(*(int (*)[4])) is the same as *(a) which is the same as *(a+0) which the same as *ptr which is : a[0] which is 1.

fix the code snippet to be:

int a[] = {1, 2, 3, 4};

fprintf(stdout,    /*you can use printf instead of fprintf(srdout,)*/
    "a      : %p\n"
    "*a     : %d\n"
    "&a     : %p\n"
    "**(&a) : %d\n",
       a,
      *a,
      &a,
   **(&a)
);