Предположим, у вас есть n указателей на строки максимум из m-1 символов (m символов, включая NULL).Таким образом, в чистом C: sizeof (char [n] [m]) вернет n * m.sizeof (char **) вернет размер указателя в вашей архитектуре, вероятно, 32 (если x86) или 64 (если x86_64).
char [n] [m] фактически выделяет байт n * mсмежно.char ** выделяет один указатель.Этот указатель ссылается на полосу памяти размером * n байт.Каждый из этих n указателей указывает на полосу памяти из m символов.
Итак, учитывая, что sizeof (char) == u, если вы объявляете char a [n] [m], когда вы используете [i] [j], компилятор понимает * (a + i * m * u + j * u).Итак, учитывая, что sizeof (char *) == w, если вы объявляете char ** a, когда вы используете [i] [j], компилятор понимает ( (a + i * w) +j * w).
Полностью другое управление данными.
Закрытие, которое вы могли бы сделать для обработки вашего особого случая, - это создать переменную char ** и заполнить ее адресами вашеговыделенная матрица стека.
char **tmp = malloc(max_strings * sizeof(char *));
int i;
for(i = 0; i < max_strings; i++){
tmp[i] = &(fill_these[i][0]); //you probably can't reference a char[][] with a single index - not confirmed
}