For better readability, you can rewrite your array definition as
array[4][5]= {
               1,2,3,4,5,             //a[0][0~4]
                6,7,8,9,10,            //a[1][0~4]
                11,12,13,14,15,        //a[2][0~4]
                16,17,18,19,20};       //a[3][0~4]
- array[2,0]is a single-level dereferencing using a single index, having a- ,comma operator.
- array[2][0]is a double-level dereferencing, using two indexes.
As per the definition of the , operator, 
the comma operator (represented by the token ,) is a binary operator
  that evaluates its first operand and discards the result, and then
  evaluates the second operand and returns this value (and type).
Now, saying printf("%d\n",array[2,0]);. get evaluated as printf("%d\n",array[0]);
Similarly,  printf("%d\n",array[3,0]); also gets evaluated to printf("%d\n",array[0]);
So, they end up producing same result.
On the other hand, printf("%d\n",&array[2][0]);, refers to the address of 1st element in the 3rd row. So it's different.
If you notice the data type, you'll find the difference easily.
- array[0]represents the data type of- int[5]
- array[2][0]represents teh data type of- int
Note: To print a pointer, you need to use %p format specifier, not %d.