How to interpret *(ptr) and *(ptr+2) in arrays?

169 views Asked by At

I don't understand how pointers works exactly in arrays.

#include <stdio.h>
int main() {

  int x[5] = {1, 2, 3, 4, 5};
  int* ptr;

  // ptr is assigned the address of the third element
  ptr = &x[2]; 

  printf("value ptr = %d \n", *ptr);   // 3
  printf("address ptr = %d \n", ptr);   // 3
  printf("value ptr+2 = %d \n", *(ptr+2)); // 4
  printf("address ptr+2 = %d \n", (ptr+2)); // 4

  return 0;
}

The result:

value ptr = 3
address ptr = -1931225192
value ptr+2 = 5
address ptr+2 = -1931225184

The difference between ptr and ptr + 2 are 8 bytes. So when ptr is equal to -1931225192 then why isn't ptr + 2 equal to -1931225192 + 2 but instead it is -1931225192 - 8?

Can someone explain how this works? Because it is logical to add 2 to the original value which was -1931225192 but instead this +2 changes into -8.

2

There are 2 answers

40
CPlus On BEST ANSWER
  1. When you add an integer to a pointer, you are not adding a fixed number of bytes. You are adding a fixed number of elements. This means you are implicitly adding n*sizeof(int) bytes. To avoid this, you can cast your array to a char * if you want to strictly add a number of bytes.

    Think about it this way: Since the ptr[n] accesses a given element and is defined to be equivalent to *(ptr + n), we see that (ptr + n) without the * simply gets the address of ptr[n].

  2. The address converted to an integer is appears to be negative number, so adding a positive value decreases its magnitude. So the +2 changes to a +8 not a -8.

0
Vlad from Moscow On

For starters these two calls of printf

printf("adress ptr = %d \n", ptr);   // 3
printf("adress ptr+2 = %d \n", (ptr+2)); // 4

have undefined behavior because there are used the incorrect conversion specifier d designed for integers to output pointers. You need to write

printf("adress ptr = %p \n", ( void * )ptr);   // 3
printf("adress ptr+2 = %p \n", ( void * )(ptr+2)); // 4

After this assignment

ptr = &x[2]; 

the pointer ptr points to the element x[2] of the array x. So dereferencing the pointer like *ptr you will get the element x[2] the value of which is equal to 3.

You may rewrite the above assignment the following way

ptr = x + 2; 

The expression ptr + 2 points to the second element of the array x after the element x[2] that is to the element x[4]. Dereferencing the expression *( ptr + 2 ) you will get the element x[4] the value of which is equal to 5.

The difference between the values of pointer expressions ptr and ptr + 2 is equal to 2 * sizeof( int ).

As you are using the incorrect conversion specifier to output pointers then you have negative numbers

adress ptr = -1931225192

and

adress ptr+2 = -1931225184

Nevrtheless the difference between these numbers is equal to 2 * sizeof( int ). As mentioned above you need to use the cirrect conversion specifier p to output valid values of the pointer expressions.

In general if you have an array for example x and a pointer ptr that is initialized by the address of the first element of the array x like for example

int x[5] = {1, 2, 3, 4, 5};
int* ptr = x;

then the expression ptr + i points to the i-th element of the array x. This is the so-called pointer arithmetic. A difference berween two points that point to elements of some array is equal to the number of elements between the elements pointed to by the pointers.

In this declaration

int* ptr = x;

the array designator x is implicitly converted to a pointer to its first element. This declaration actually is equivalent to

int* ptr = &x[0];