Чтобы было понятно, вы можете переписать это объявление
char *xx[401];
как
char * ( xx[401] );
То есть это массив с 401 элементом типа char *.
Указатель на этот массив будет выглядеть как
char * ( *pxx )[401] = &xx;
Указатель на элемент массива будет выглядеть как
char ** pxx = xx;
Если вы хотите динамически распределить массив с 401 элементом тип char *, тогда код может выглядеть следующим образом:
char ** pxx = malloc( 401 * sizeof( char * ) );
Вот демонстрационная программа, которая показывает, как можно динамически размещать массив указателей на символьные массивы.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
enum { N = 2, M = 6 };
const char * hello[N] = { "Hello", "World" };
char **s = malloc( N * sizeof( char * ) );
for ( size_t i = 0; i < N; i++ )
{
s[i] = malloc( M );
strcpy( s[i], hello[i] );
}
for ( size_t i = 0; i < N; i++ )
{
if ( i != 0 ) putchar( ' ' );
printf( "%s", s[i] );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
free( s[i] );
}
free( s );
return 0;
}
Программа вывод
Hello World