You can look at the below which may be surprising, bu works fine, but using qsort instead of bubble sort...
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int myfunction (int* i,int* j) { return (*i>*j); }
int main (){
int x[4][4],i,k,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
x[i][j] = random()%1000;
qsort((void*)x, 16, sizeof(int),(int (*)(const void*,const void*))myfunction);
for(i=0;i<4;i++) {
for(j=0;j<4;j++)
cout<<x[i][j]<<"\t";
cout<<"\n\n";
}
}
There is a trick here, in as that we are just sorting a one-dimensional array using qsort. The trick is possible because the memory layout of x[4][4] is 16 consecutive integers, so you can access just as if it was declared as x[16] -- and you can use this fact to also implement a traditional bubble sort, just casting int y = (int)x; and then sorting y from (0..15) as it was a one dimensional array.
However I would not recommend this if you are a novice to intermediate programmer in C/C++, as you probably will get it horribly wrong -- also you probably will not get any performance gains in doing so, as the optimizer is pretty good and unrolling loops, and the modern pipe-line CPU are very fast in executing tight loops like your above.
Update
As a bubble sort, the following works with only two loops;
for(i=0;i<16;i++)
for(j=i;j<16;j++)
if(x[i/4][i%4]>x[j/4][j%4])
{
int temp = x[i/4][i%4];
x[i/4][i%4] = x[j/4][j%4];
x[j/4][j%4] = temp;
}
If you do insist on having individual loops of each dimension, then this is the right way;
for (int ia=0; ia <4; ia++)
for (int ja=0; ja <4; ja++)
for (int ib=0; ib <4; ib++)
for (int jb=0; jb <4; jb++)
if(x[ia][ib]<x[ja][jb])
{
int temp = x[ia][ib];
x[ia][ib] = x[ja][jb];
x[ja][jb] = temp;
}