Reputation: 2210
A method that returns a string array. For some reason this method fails while accessing the string values specifically for the last NULL
value.
static char **getList() {
char **list = (char *[]){"ABC", "DEF", NULL};
char **interests = malloc(sizeof(char*) * 3);
int i = 0;
while(*list) {
interests[i] = malloc(sizeof(char) * strlen(*list));
strcpy(interests[i++], *list);
list++;
}
return interests;
}
Using
char **interests = getList();
while(*interests) {
puts(*interests);
interests++;
}
Attached screenshot.
Upvotes: 0
Views: 65
Reputation: 409482
You do some... weird things in the code you show. To begin with we have the list
variable, which should be a simple and plain array instead.
And if the array or its contents should not be modified then you could even create an array whose life-time last the full run-time of the program, using static
:
static const char * const *getList() {
static const char * const list[] = { "ABC", "DEF", NULL };
return list;
}
The declaration const char * const list[]
declares list
as an array (whose size will be deduced from the initialization) of constant pointers to constant characters. That is, the pointers inside list
can't be modified, and the string contents itself can't be modified.
If you have other requirements, like being able to modify the strings, then you could still use the definition shown above in my answer, but create a new array to return.
There are a few improvements that can be made to the allocation and copying code as well. For example you could programatically get the size of the array list
. I also recommend that you use a simple index loop instead of the pointer arithmetic loop you have now, and with the correct size of the list
array the loop will include copying the terminating NULL
as well.
All in all it could look something like
static char **getList() {
static const char * const list[] = { "ABC", "DEF", NULL };
// Get the number of elements in the array
size_t list_size = sizeof list / sizeof list[0];
// sizeof *interests is the size of each element we want to allocate
// multiply it by the number of elements we need
char **interests = malloc(sizeof *interests * list_size);
// Do a deep copy of the strings from list
for (size_t i = 0; i < list_size ++i) {
if (list[i] == NULL) {
interests[i] = NULL;
} else {
interests[i] = malloc(strlen(list[i]) + 1); // +1 for the string terminator
strcpy(interests[i], list[i]);
// Or if your system have the strdup function (which is quite common)
// interests[i] = strdup(list[i]);
}
}
return interests;
}
If you don't need a deep copy, then the copying loop could be:
for (size_t i = 0; i < list_size ++i) {
interests[i] = list[i];
}
Upvotes: 0
Reputation: 75062
strlen()
, the allocation lack for space for terminating null-character.interestes
, which should be NULL
, is not initialized.fixed version:
static char **getList() {
char **list = (char *[]){"ABC", "DEF", NULL};
char **interests = malloc(sizeof(char*) * 3);
int i = 0;
while(*list) {
interests[i] = malloc(sizeof(char) * (strlen(*list) + 1)); /* allocate one more */
strcpy(interests[i++], *list);
list++;
}
interests[i] = NULL; /* initialize the last element */
return interests;
}
Upvotes: 1