Вы можете буквально изменить свой код таким образом, чтобы вы лучше его поняли:
int main()
{
int** wsk = new int* [2];
int* wsk0 = new int[2], *wsk1 = new int[2];
wsk[0] = wsk0;
wsk[1] = wsk1;
Вы генерируете три разных указателя. Первый содержит два указателя. Все три указателя указывают на разделенные адреса.
Следующие конструкции содержат один постоянный указатель, указывающий на непрерывную ячейку памяти, содержащую четыре элемента, поэтому в этом случае & msx будет равен wsk и будет равен & wsk [0] и & wsk [0] [0] также:
int main()
{
int wsk[2][2]; //in mmemory elements are located one by one
cout << reinterpret_cast<long>( &wsk) << endl;
cout << reinterpret_cast<long>( wsk) << endl;
cout << reinterpret_cast<long>( &wsk[0]) << endl;
cout << reinterpret_cast<long>( &wsk[0][0]) << endl;