Multidimensional arrays in C are just arrays-of-arrays, since that you can check sizeof between each sub-array like that:
#include <stdio.h>
int main(void)
{
    int a[5][3][6];
    int dimx, dimy, dimz;
    dimx = (int) (sizeof a / sizeof a[0]);
    dimy = (int) (sizeof a[0] / sizeof a[0][0]);
    dimz = (int) (sizeof a[0][0] / sizeof a[0][0][0]);
    printf("dimx = %d, dimy = %d, dimz = %d\n", dimx, dimy, dimz);
    return 0;
}
Result:
dimx = 5, dimy = 3, dimz = 6
Note that sizeof operator returns result as of type size_t, so it might be better to cast its results (in order to avoid e.g. warning by -Wconversion flag in GCC). You might also want to create function-like macros if you like e.g.:
#define ARRAY_SIZE_3D_X(a) ((int) (sizeof a / sizeof a[0])
#define ARRAY_SIZE_3D_Y(a) ((int) (sizeof a[0] / sizeof a[0][0])
#define ARRAY_SIZE_3D_Z(a) ((int) (sizeof a[0][0] / sizeof a[0][0][0])
Edit:
As pointed by @pmg if you prefer size_t type directly, then use the following instead:
#include <stdio.h>
int main(void)
{
    int a[5][3][6];
    size_t dimx, dimy, dimz;
    dimx = sizeof a / sizeof a[0];
    dimy = sizeof a[0] / sizeof a[0][0];
    dimz = sizeof a[0][0] / sizeof a[0][0][0];
#if __STDC_VERSION__ >= 199901L
    printf("dimx = %zu, dimy = %zu, dimz = %zu\n", dimx, dimy, dimz);
#else
    printf("dimx = %lu, dimy = %lu, dimz = %lu\n", (unsigned long) dimx,
           (unsigned long) dimy, (unsigned long) dimz);
#endif
    return 0;
}
Note that due usual arithmetic conversions it's problematic to mix signed and unsigned values in single expression (e.g. int and unsigned long), as if unsigned type has rank that is greater or equal than signed type, then signed value is promoted to unsigned, e.g. -5 is now some large integer.