Есть несколько подходов. Самое простое - объявить массив массивов char следующим образом:
char strs[N][M + 1]; // M is max length of each string
...
strcpy(strs[i], "foo");
Вся память для строк распределяется статически, но размер каждой строки в массиве фиксирован, и вам необходимо выбрать размер для максимально длинной строки, что может привести к некоторой внутренней фрагментации. Все строки доступны для записи.
Другой подход заключается в объявлении массива указателей на char:
char *strs[N];
...
strs[i] = malloc(strlen("bar") + 1);
if (strs[i])
strcpy(strs[i], "bar");
Таким образом, вы можете выделить столько памяти, сколько нужно для каждой строки массива, или изменить размер строк, если это необходимо. Вы также можете просто указать на строковые литералы, но помните, что литералы могут быть недоступны для записи; то есть вы, возможно, не сможете сделать что-то вроде:
strs[j] = "foo";
strs[j][0] = 'b'; // may not be allowed on string literal
Вы можете динамически распределить весь smash:
char **strs = malloc(sizeof *strs * N);
for (i = 0; i < N; i++)
strs[i] = malloc(SIZE + 1);
Этот подход позволяет вам не только изменять размер каждой строки по мере необходимости, но и изменять количество строк. Обратите внимание, что в этом случае strs является , а не типом массива, даже если он обрабатывается как массив.
Обратите внимание, что лучшие практики в отношении malloc () различаются в C и C ++. В C считается плохой практикой приводить результат malloc (). Во-первых, это не нужно, поскольку указатели void неявно приводятся к другим типам указателей объектов. С другой стороны, он отключит диагностику, если вы забудете #include stdlib.h или у вас нет прототипа для malloc () в области видимости. Помните, что если C не видит прототип функции до того, как на нее ссылаются, он будет предполагать, что функция возвращает int, который не может быть неявно преобразован в тип указателя.