Как отмечено в комментариях, две ваши проблемы заключаются в том, что вы намереваетесь изменить константы строковых литералов и что поведение вашей функции зависит от свойств вашей структуры данных (т. Е. Правильно завершенных строк и указателя NULL в качестве последнего элемента),
Поэтому я предлагаю настроить структуру данных фиксированного размера во время запуска, затем установить и изменить содержимое и, наконец, снова все очистить - как это:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define LEN 10
#define NUM 3
char **init (int num, int len) {
char **strings = calloc(num, sizeof(char*));
for (int i=0; i < num; i++) {
strings[i] = calloc(len, sizeof(char));
}
return strings;
}
void teardown (char **strings, int num) {
for (int i=0; i < num; i++) {
free(strings[i]);
}
free(strings);
}
void to_lower(char **strings, int num, int len) {
for (int i=0; i < num; i++) {
for (int j=0; j < len; j++)
strings[i][j] = tolower(strings[i][j]);
}
}
int main(void) {
// startup
char **strings = init(NUM, LEN);
// do things
sprintf(strings[0], "%s", "Hello");
sprintf(strings[1], "%s", "Zerotom");
sprintf(strings[2], "%s", "new");
to_lower(strings, NUM, LEN);
// shutdown
teardown(strings, NUM);
return 0;
}