C Asterisk Operator Using

64 Views Asked by At

im trying to learn pointers and im confused in second line, can someone explain how it works?

if we suppose 'a' base address is 100

  int a[3][3] = {6, 2, 5, 0, 1, 3, 4, 9, 8};
  printf("%p \n", a+1); // output is gonna be 112
  printf("%p \n", *(a+1));// still output is gonna be 112
    

How does the pointer arithmetic and the dereference operator (*) work in the second line of code? Why does the printf statement printf("%p \n", *(a+1)); output the memory address 112 instead of the integer value at that address? Thanks in advance

2

There are 2 best solutions below

0
Some programmer dude On BEST ANSWER

Remember that for any array or pointer a and index i, the expression a[i] is exactly the same as *(a + i).

If we apply it to your example, then a + 1 is a pointer to the second element of the array a. It's the same as &a[1].

And *(a + 1) is a[1], which is an array and therefore will decay to a pointer to its first element, meaning that a[1] is the same as &a[1][0].

While these two pointers, &a[1] and &a[1][0], have different types, they both point to the same location. Which is very easy to see once we draw it out, with the pointers added:

+---------+---------+---------+---------+--------------------+
| a[0][0] | a[0][1] | a[0][2] | a[1][0] | ... (not relevant) |
+---------+---------+---------+---------+--------------------+
                              ^
                              |- &a[1]
                              |- &a[1][0]

To expand on the different types, &a[1] is a pointer to an array of three int elements, or int (*)[3].

The other pointer, &a[1][0], is a pointer to a single int element, and therefore have the type int *.

0
Vlad from Moscow On

An array designator used in expression with rare exceptions is converted to pointer to its first element.

From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)

3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

In the provided code snippet the array a is declared like

int a[3][3] = {6, 2, 5, 0, 1, 3, 4, 9, 8};

So in the expression a + 1 the array designator a is converted to pointer of the type int ( * )[3]. That is it is a pointer to the first element ("row") of the array. Thus the expression a + 1 points to the second element ("row") of the type int[3] of the array. The value of the address produced of the expression a + 1 differs from the address of the first element of the array by the value sizeof( int[3] ). If sizeof( int ) is equal to 4 then the difference between the addresses if equal to 3 * sizeof( int ) that is to 12.

As for this expression *( a + 1 ) then dereferencing the expression a + 1 it yields the second element of the array of the type int[3]. Used as an expression in the call of printf the array designator *( a + 1 ) having the type int[3] again is implicitly converted to pointer of the type int * to its first element. The addresses of the first element of the second "row" and of the second "row" itself are equal each other though they have different types.

For example these calls of printf:

printf( "Address of &a = %p\n", ( void * )&a );
printf( "Address of a = %p\n", ( void * )a );
printf( "Address of &a[0] = %p\n", ( void * )&a[0] );
printf( "Address of a[0] = %p\n", ( void * )a[0] );
printf( "Address of &a[0][0] = %p\n", ( void * )&a[0][0] );

will output the same address value though types of the used expressions are different. The types of the expressions (taking into account the implicit conversion of array designators to pointers to their first elements) are (from top to bottom):

&a       -> int ( * )[3][3]
a        -> int ( * )[3]
&a[0]    -> int ( * )[3]
a[0]     -> int *
&a[0][0] -> int *