You as the programmer need to decide how will you store the data. You have multiple options, bear in mind that:
- 'string' is an array characters stored terminated with a zero byte, ie. '\0'
- You need to store how many array elements there are in an array.
- In case of 'strings' the number of elements in an array / the number of characters in a string may be computed by counting the number of characters until the zero byte '\0' is encountered.
- For all other arrays you have two options.
- You explicitly set the last array member to NULL/zero, like you did in case of str_arr1[] = { "sdfddsf", "foo1", 0 };. When copying such array you need to remember to explicitly set the last member to zero. In this case you will often see a magic+ 1in code when calculating size, likemalloc(sizeof(char) * (strlen(string) + 1)).
- You can store the array size in a separate variable, typically of size_ttype.
 
- You have 3 arrays of strings, ie. three arrays terminated by NULL of array terminated by zero byte of characters.
- You want to have an array of arrays of strings. You need to decide how will you track the size of that array and the size of inside arrays.
- I don't like having an explicit array termination value. I like storing sizes of an array using separate variable of type size_t. Usually I wrap a pointer to the array and the variable that stores the size in one structure. That way I can write separate libraries for each level of array.
- Please don't decide for char ***var;. It makes code unreadable.
#define _GNU_SOURCE  1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void store_pointers_to_arrys_of_strings_null_delimeterd(
    const char * const * const strings_to_copy[], size_t strings_to_copy_len)
{
    const char * const **the_arrays;
    // alloc memory
    const size_t the_arrays_len = strings_to_copy_len + 1;
    the_arrays = malloc(sizeof(the_arrays) * the_arrays_len);
    if (the_arrays == NULL) {
        perror("malloc failed\n");
        abort();
    }
    // copy pointers
    for (size_t i = 0; i < strings_to_copy_len; ++i) {
        the_arrays[i] = strings_to_copy[i];
    }
    the_arrays[strings_to_copy_len] = NULL;
    for (size_t i = 0; the_arrays[i] != NULL; ++i) {
        for (size_t j = 0; the_arrays[i][j] != NULL; ++j) {
            printf("%s: %zu %zu %s\n", __func__, i, j, the_arrays[i][j]);
        }
    }
    free(the_arrays);
}
void store_strings_themselves_as_arrays_of_strings_null_delimeterd(
    const char * const * const strings_to_copy[], size_t strings_to_copy_len)
{
    const char ***the_arrays;
    // allocate for arrays
    const size_t the_arrays_len = strings_to_copy_len + 1;
    the_arrays = malloc(sizeof(the_arrays) * the_arrays_len);
    if (the_arrays == NULL) {
        perror("malloc failed\n");
        abort();
    }
    // copy strings
    for (size_t i = 0; i < strings_to_copy_len; ++i) {
        size_t cnt = 1;
        for (size_t j = 0; strings_to_copy[i][j] != NULL; ++j) {
            ++cnt;
        }
        the_arrays[i] = malloc(sizeof(the_arrays[i]) * cnt);
        memcpy(the_arrays[i], strings_to_copy[i], cnt * sizeof(the_arrays[i]));
    }
    the_arrays[strings_to_copy_len] = NULL;
    // print
    for (size_t i = 0; the_arrays[i] != NULL; ++i) {
        for (size_t j = 0; the_arrays[i][j] != NULL; ++j) {
            printf("%s: %zu %zu %s\n", __func__, i, j, the_arrays[i][j]);
        }
    }
    // free
    for (size_t i = 0; the_arrays[i] != NULL; ++i) {
        free(the_arrays[i]);
    }
    free(the_arrays);
}
void store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd(
    const char * const * const strings_to_copy[], size_t strings_to_copy_len)
{
    char ***the_arrays;
    // allocate for arrays
    const size_t the_arrays_len = strings_to_copy_len + 1;
    the_arrays = malloc(sizeof(the_arrays) * the_arrays_len);
    if (the_arrays == NULL) {
        perror("malloc failed\n");
        abort();
    }
    // copy string pointers
    for (size_t i = 0; i < strings_to_copy_len; ++i) {
        size_t cnt = 0;
        for (size_t j = 0; strings_to_copy[i][j] != NULL; ++j) {
            ++cnt;
        }
        // allocate memory for string pointers
        const size_t the_arrays_i_len = cnt + 1;
        the_arrays[i] = malloc(sizeof(the_arrays[i]) * the_arrays_i_len);
        if (the_arrays[i] == NULL) { perror("AA"); abort(); }
        // copy the strings themselves
        for (size_t k = 0; k < cnt; ++k) {
            the_arrays[i][k] = strdup(strings_to_copy[i][k]);
            if (the_arrays[i][k] == NULL) { perror("AA"); abort(); }
        }
        the_arrays[i][cnt] = NULL;
    }
    the_arrays[strings_to_copy_len] = NULL;
    // print
    for (size_t i = 0; the_arrays[i] != NULL; ++i) {
        for (size_t j = 0; the_arrays[i][j] != NULL; ++j) {
            printf("%s: %zu %zu %s\n", __func__, i, j, the_arrays[i][j]);
        }
    }
    // free
    for (size_t i = 0; the_arrays[i] != NULL; ++i) {
        for (size_t j = 0; the_arrays[i][j] != NULL; ++j) {
            free(the_arrays[i][j]);
        }
        free(the_arrays[i]);
    }
    free(the_arrays);
}
void store_pointers_to_arrays_of_strings_in_a_struct(
    const char * const * const strings_to_copy[], size_t strings_to_copy_len)
{
    struct arrays_of_array_of_strings_s {
        const char * const **strs;
        size_t strscnt;
    };
    const size_t the_arrays_cnt = strings_to_copy_len;
    struct arrays_of_array_of_strings_s the_arrays;
    the_arrays.strs = malloc(sizeof(the_arrays.strs[0]) * the_arrays_cnt);
    if (the_arrays.strs == NULL) {
        perror("malloc failed\n");
        abort();
    }
    // fill array
    for (size_t i = 0; i < strings_to_copy_len; ++i) {
        the_arrays.strs[i] = strings_to_copy[i];
    }
    the_arrays.strscnt = the_arrays_cnt;
    // print
    for (size_t i = 0; i < the_arrays.strscnt; ++i) {
        for (size_t j = 0; the_arrays.strs[i][j] != NULL; ++j) {
            printf("%s: %zu %zu %s\n", __func__, i, j, the_arrays.strs[i][j]);
        }
    }
    // free
    free(the_arrays.strs);
    the_arrays.strscnt = 0;
}
void store_pointers_to_strings_in_array_of_structs(
    const char * const * const strings_to_copy[], size_t strings_to_copy_len)
{
    struct array_of_strings_s {
        const char * const *strs;
    };
    const size_t the_arrays_cnt = strings_to_copy_len;
    struct array_of_strings_s * const the_arrays = malloc(sizeof(the_arrays[0]) * the_arrays_cnt);
    if (the_arrays == NULL) {
        perror("malloc failed\n");
        abort();
    }
    // fill array
    for (size_t i = 0; i < strings_to_copy_len; ++i) {
        the_arrays[i].strs = strings_to_copy[i];
    }
    // print
    for (size_t i = 0; i < the_arrays_cnt; ++i) {
        for (size_t j = 0; the_arrays[i].strs[j] != NULL; ++j) {
            printf("%s: %zu %zu %s\n", __func__, i, j, the_arrays[i].strs[j]);
        }
    }
    // free
    free(the_arrays);
}
void store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null(
    const char * const * const strings_to_copy[], size_t strings_to_copy_len)
{
    struct array_of_strings_s {
        const char * *arrstrs;
    };
    const size_t the_arrays_cnt = strings_to_copy_len + 1;
    struct array_of_strings_s * const the_arrays = malloc(sizeof(the_arrays[0]) * the_arrays_cnt);
    if (the_arrays == NULL) {
        perror("malloc failed\n");
        abort();
    }
    // fill array
    for (size_t i = 0; i < strings_to_copy_len; ++i) {
        size_t cnt = 0;
        for (size_t j = 0; strings_to_copy[i][j] != NULL; ++j) {
            ++cnt;
        }
        const size_t the_arrays_i_strs_cnt = cnt + 1;
        the_arrays[i].arrstrs = malloc(sizeof(the_arrays[i].arrstrs[0]) * cnt);
        if (the_arrays[i].arrstrs == NULL) { perror("AA"); abort(); }
        for (size_t k = 0; k < cnt; ++k) {
            the_arrays[i].arrstrs[k] = strings_to_copy[i][k];
        }
        the_arrays[i].arrstrs[cnt] = NULL;
    }
    the_arrays[strings_to_copy_len].arrstrs = NULL;
    // print
    for (size_t i = 0; the_arrays[i].arrstrs != NULL; ++i) {
        for (size_t j = 0; the_arrays[i].arrstrs[j] != NULL; ++j) {
            printf("%s: %zu %zu %s\n", __func__, i, j, the_arrays[i].arrstrs[j]);
        }
    }
    // free
    for (size_t i = 0; the_arrays[i].arrstrs != NULL; ++i) {
        free(the_arrays[i].arrstrs);
    }
    free(the_arrays);
}
void store_strings_in_array_of_strings_in_array_of_array_of_strings_in_a_struct(
    const char * const * const strings_to_copy[], size_t strings_to_copy_len)
{
    struct string_s {
        char *str;
    };
    struct array_of_strings_s {
        struct string_s *strs;
        size_t strscnt;
    };
    struct array_of_arrays_of_strings_s {
        struct array_of_strings_s *arrstrs;
        size_t arrstrscnt;
    };
    struct array_of_arrays_of_strings_s the_arrays;
    // fill array
    the_arrays.arrstrscnt = strings_to_copy_len;
    the_arrays.arrstrs = malloc(sizeof(the_arrays.arrstrs[0]) * the_arrays.arrstrscnt);
    if (the_arrays.arrstrs == NULL) { perror("malloc failed\n"); abort(); }
    for (size_t i = 0; i < the_arrays.arrstrscnt; ++i) {
        struct array_of_strings_s * const array_of_strings = &the_arrays.arrstrs[i];
        size_t cnt = 0;
        for (size_t j = 0; strings_to_copy[i][j] != NULL; ++j) {
            ++cnt;
        }
        array_of_strings->strscnt = cnt;
        array_of_strings->strs = malloc(sizeof(array_of_strings->strs[0]) * array_of_strings->strscnt);
        if (array_of_strings->strs == NULL) { perror("AA"); abort(); }
        for (size_t k = 0; k < array_of_strings->strscnt; ++k) {
            struct string_s * const string = &array_of_strings->strs[k];
            string->str = strdup(strings_to_copy[i][k]);
            if (string->str == NULL) { perror("AA"); abort(); }
        }
    }
    // print
    for (size_t i = 0; i < the_arrays.arrstrscnt; ++i) {
        for (size_t j = 0; j < the_arrays.arrstrs[i].strscnt; ++j) {
            printf("%s: %zu %zu %s\n", __func__, i, j, the_arrays.arrstrs[i].strs[j].str);
        }
    }
    // free
    for (size_t i = 0; i < the_arrays.arrstrscnt; ++i) {
        struct array_of_strings_s * const array_of_strings = &the_arrays.arrstrs[i];
        for (size_t j = 0; j < array_of_strings->strscnt; ++j) {
            struct string_s * const string = &array_of_strings->strs[i];
            free(string->str);
        }
        free(array_of_strings->strs);
    }
    free(the_arrays.arrstrs);
}
int main()
{
    // "blabla" is a string literal - it's a immutable sting
    const char * const str_arr1[] = { "sdfddsf", "foo1", NULL };
    const char * const str_arr2[] = { "sdsosdfrt", "foo2", NULL };
    const char * const str_arr3[] = { "grsdsfdep", "foo3", NULL };
    // or char `str_arr1[][] = { .... };`
    // string literal are immutable, read-only
    // so `const char *var = "abc";` or string initialization like `char var[] = "abc";`
    // just an array of strings to copy
    const char * const * const strings_to_copy[] = { str_arr1, str_arr2, str_arr3 };
    const size_t strings_to_copy_len = sizeof(strings_to_copy)/sizeof(strings_to_copy[0]);
    store_pointers_to_arrys_of_strings_null_delimeterd(
        strings_to_copy, strings_to_copy_len);
    store_strings_themselves_as_arrays_of_strings_null_delimeterd(
        strings_to_copy, strings_to_copy_len);
    store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd(
        strings_to_copy, strings_to_copy_len);
    store_pointers_to_arrays_of_strings_in_a_struct(
        strings_to_copy, strings_to_copy_len);
    store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null(
        strings_to_copy, strings_to_copy_len);
    store_pointers_to_strings_in_array_of_structs(
        strings_to_copy, strings_to_copy_len);
    return 0;
}
Will output:
store_pointers_to_arrys_of_strings_null_delimeterd: 0 0 sdfddsf                                                                                                                    
store_pointers_to_arrys_of_strings_null_delimeterd: 0 1 foo1                                                                                                                       
store_pointers_to_arrys_of_strings_null_delimeterd: 1 0 sdsosdfrt                                                                                                                  
store_pointers_to_arrys_of_strings_null_delimeterd: 1 1 foo2                                                                                                                       
store_pointers_to_arrys_of_strings_null_delimeterd: 2 0 grsdsfdep                                                                                                                  
store_pointers_to_arrys_of_strings_null_delimeterd: 2 1 foo3                                                                                                                       
store_strings_themselves_as_arrays_of_strings_null_delimeterd: 0 0 sdfddsf                                                                                                         
store_strings_themselves_as_arrays_of_strings_null_delimeterd: 0 1 foo1                                                                                                            
store_strings_themselves_as_arrays_of_strings_null_delimeterd: 1 0 sdsosdfrt                                                                                                       
store_strings_themselves_as_arrays_of_strings_null_delimeterd: 1 1 foo2                                                                                                            
store_strings_themselves_as_arrays_of_strings_null_delimeterd: 2 0 grsdsfdep                                                                                                       
store_strings_themselves_as_arrays_of_strings_null_delimeterd: 2 1 foo3                                                                                                            
store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd: 0 0 sdfddsf                                                                                        
store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd: 0 1 foo1                                                                                           
store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd: 1 0 sdsosdfrt                                                                                      
store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd: 1 1 foo2                                                                                           
store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd: 2 0 grsdsfdep                                                                                      
store_strings_in_array_of_strings_in_array_of_array_of_strings_null_delimeterd: 2 1 foo3                                                                                           
store_pointers_to_arrays_of_strings_in_a_struct: 0 0 sdfddsf                                                                                                                       
store_pointers_to_arrays_of_strings_in_a_struct: 0 1 foo1                                                                                                                          
store_pointers_to_arrays_of_strings_in_a_struct: 1 0 sdsosdfrt                                                                                                                     
store_pointers_to_arrays_of_strings_in_a_struct: 1 1 foo2                                                                                                                          
store_pointers_to_arrays_of_strings_in_a_struct: 2 0 grsdsfdep                                                                                                                     
store_pointers_to_arrays_of_strings_in_a_struct: 2 1 foo3                                                                                                                          
store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null: 0 0 sdfddsf                                                                       
store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null: 0 1 foo1                                                                          
store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null: 1 0 sdsosdfrt                                                                     
store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null: 1 1 foo2                                                                          
store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null: 2 0 grsdsfdep                                                                     
store_strings_in_an_array_of_structs_delimeterd_by_null_of_arrays_of_strings_delimeterd_by_null: 2 1 foo3                                                                          
store_pointers_to_strings_in_array_of_structs: 0 0 sdfddsf                                                                                                                         
store_pointers_to_strings_in_array_of_structs: 0 1 foo1                                                                                                                            
store_pointers_to_strings_in_array_of_structs: 1 0 sdsosdfrt                                                                                                                       
store_pointers_to_strings_in_array_of_structs: 1 1 foo2                                                                                                                            
store_pointers_to_strings_in_array_of_structs: 2 0 grsdsfdep                                                                                                                       
store_pointers_to_strings_in_array_of_structs: 2 1 foo3                       
Live version available at onlinegdb.