Question: ```
int array[10] = {1,2,3,4,5,6,7,8};
int *ptr = array;
std::cout<<*(ptr+ 2); => O/P = 3

int (*arr_ptr)[10] = &array;
std::cout<<*(*arr_ptr+2); => O/P = 3

```

Whats the difference between these 2. I know what they mean, but if they give same result why do we have 2 different notations?

Answer: 
The first case is the normal case: `ptr` is a pointer to the first element of the array `array`, and it is indexed (using `*(ptr+2)`, which is a synonym for `ptr[2]`) to access the third element of that array.

The second case is contrived: `arr_ptr` is a pointer to the (enitre) array `array`. It is first dereferenced (with `*arr_ptr`) to yield the array itself, which is then used as an argument to binary `+`, which causes it to get implicitly converted to a (nameless) pointer to its first element, which is then indexed in the same way `*(<nameless pointer>+2)` and gives the same result.

Making those implicit conversions explicit, you could write

```
int *ptr = &array[0];
std::cout<<*(ptr+ 2);

int (*arr_ptr)[10] = &array;
std::cout<<*( &(*arr_ptr)[0] + 2 );

```
Use the notation that you understand and that fits the problem domain. If your app has an array, then use array notation. If you have to push pointers around for some other reason, then the second version is appropriate.