char string[40]
is an array of 40 characters that can hold 39 characters maximum (plus the string terminator) - the maximum size cannot be changed and 40 bytes of memory are used even if you store a short string containing 2 characters (plus the string terminator).
char *string
is a pointer to some characters - the pointer can point anywhere: to a single character or any size array of characters. If it points to an array of characters (which you can make using malloc() then it can be thought of as a "string")
char *array[8]
is an array of 8 "strings" (really it is 8 pointers to characters) The size of the array cannot be changed but the pointers can point anywhere: to a single character or any size array of characters. If the pointers point to an array of characters (which you can make using malloc() then they can be thought of as "strings")
char array[8][40]
is a 2D array which you can think of as an array of 8 "strings" - where "strings" is defined as an array of 40 characters that can hold 39 characters maximum (plus the string terminator). You cannot change the size of either dimension.
char **array
is a pointer to a char *
- which could just be a single "string" or to an array of "strings". The sizes aren't fixed and can be dynamically created.
char *string1 = "asd";
means that string1 points to an array of 4 characters ("asd" plus the string terminator) that are in read-only memory - you cannot change the contents of the string but you can point string1 anywhere you want.
char string1[] = "asd";
means that string1 is an array of 4 characters that are filled up by the compiler with 4 characters ("asd" plus the string terminator) - you can change the contents of the array but you can't change the size.
So if you want a dynamically sized array of character strings you can do this:
#include <stdio.h> // printf
#include <stdlib.h> // malloc, realloc, free
#include <string.h> // strcpy, strdup
int main()
{
// make an array of 8 string pointers
int original_size = 8;
char **array = malloc(original_size * sizeof(char *));
// point each pointer to a string
// you don't have to do this all at once if you don't want to
for (int i=0; i<original_size; i++)
array[i] = malloc(40 * sizeof(char)); // max of 39 plus the terminator
// array[7] is already allocated so we can just use it as a string
strcpy(array[7],"asd"); // the last string that we malloced
// reallocate the array to be bigger
int new_size = 15;
array = realloc(array, new_size * sizeof(char *));
// array[14] is a pointer that doesn't point anywhere
// so we need to allocate space before filling it in
array[14] = strdup("qwe"); // points 3 characters plus the string terminator
printf("%s\n",array[7]);
printf("%s\n",array[14]);
// free the one we made with strdup
free(array[14]);
// free the 8 we malloced
for (int i=0; i<original_size; i++)
free(array[i]);
// now free the array we malloced and then realloced
free(array);
return 0;
}
Note: there is NO error checking in that program because I didn't want to mask the basic ideas - make sure you add error checking to any program you make
Try it at https://onlinegdb.com/XQeyOGd0C