Actually you are defining an array of arrays of integers. It can decay to a pointer to an array of integers, but it will not decay into a pointe to a pointer of integers.
It will help if you draw the memory layout:
+---------+---------+---------+---------+
| a[0][0] | a[0][1] | a[1][0] | a[1][1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
If you let it decay into a pointer-to-array-of-integer:
int (*pa)[2] = a;
+---------+---------+---------+---------+
| pa[0] | pa[1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
Note how sizeof(*pa) = 2 * sizeof(int)
. Each of these values can decay into a pointer to integer, but never into a pointer to a pointer:
int *p = pa[0];
Anyway, you can cast the decayed pointer-to-array-of-integer into a pointer to integers and access the four values directly:
int *p = (int*)a;
std::cout << p[3] << std::endl;
std::cout << *(p + 3) << std::endl;
The memory will be like this:
+---------+---------+---------+---------+
| p[0] | p[1] | p[2] | p[3] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
But if you cast it into a int**
you will get meaningless values, because in memory there are no pointers, just integers.