Why does * need to be put before (&a) to subtract a (a is an array)?

The memory address of the array is the same as the memory address of the first element, and when you add to or subtract from a pointer, it is done by the size of the type it points to, so:

  • arr refers to int, and &arr refers to int[5].
  • &arr+1 increments the memory address in the size of five integers.
  • If you do (&arr+1)-arr you get a compile error, because they are different types.
  • If you do (&arr+1)-&arr you get 1, because the offset of the memory address is the same as one size of int[5].
  • Therefore, when you do *(&arr+1), you get the same memory address but pointing to int and not int[5]. Now you wont get a compile error, because both pointers point to int and you get the offset of the memory address in terms of int size, and not int[5]. Memory addresses and types are quite difficult to explain sometimes, I hope I made it clear. Here you have some code you can run to see some of the concepts mentioned:
   int arr[5] = {5, 8, 1, 3, 6};
   int len = *(&arr + 1) - arr;
   cout << "arr: " << arr << endl;
   cout << "arr + 1: " << arr+1 << endl;
   cout << "&arr: " << &arr << endl;
   cout << "&arr + 1: " << &arr+1 << endl;
   cout << "*(&arr + 1): " << *(&arr+1) << endl;
   // cout << "&arr + 1 - arr: " << &arr+1-arr << endl;
   // error: invalid operands of types ‘int (*)[5]’ and ‘int [5]’ to binary ‘operator-’

   cout << "The length of the array is: " << len;

The type of the array arr is int[5], the type of &arr is int(*)[5]. (&arr + 1) increases the array address on sizeof(int[5]) as it's done by the rules of the pointer arithmetic, i.e. computes the address after the array. *(&arr + 1) is int[5], an array right after arr, where arr[5] would place. The both arguments of the substractions decay to int*. The substraction of pointers to int gives 5.

This may be considered as undefined behavior, since substraction of pointers belonging to different object storages is not defined. Also results of expressions with pointers addressing unallocated memory (like the (&arr + 1)) are undefined.