0

I have a struct defined as following:

typedef char *element_t;

typedef
struct {
  element_t *array;     /* start of the array */
  int capacity;         /* number of elements the array */
  int length;           /* used portion of array, 0..capacity */
} list;

I am trying to access the array that *array points to and assign it a char value and print it.

I'm a bit rusty with C but this is how i'm trying to do it:

list.array[0] = "a";
printf("%s\n", list.array[0]);

This makes my program crash. Any fixes?

EDIT: I should also mention that I have done the following initialisations too:

element_t* array[LMAX];
list.array= *differentArray;
bawse
  • 130
  • 4
  • 21
  • Are you assigning `list.array` to point to a valid array before the `list.array[0]` is accessed? – juhist Mar 25 '15 at 10:50
  • Just addressed that issue in my most recent edit in the OP – bawse Mar 25 '15 at 10:50
  • `array` is a pointer to pointer to char. You have to `strcpy(list.array[0],"a");` But this can crash too. You can first `malloc` it. – ForceBru Mar 25 '15 at 10:51
  • 1
    `list` is the name of a type. `list.array[0]` is an error because `.` can only be applied to objects. – M.M Mar 25 '15 at 10:52
  • Well, as my code example shows, `list` can also be a variable name in addition to being a name of a type. – juhist Mar 25 '15 at 10:54
  • 1
    It is however incredibly stupid practice to name your variables the same as the type... – Lundin Mar 25 '15 at 10:56
  • 1
    ...if it actually was a type. This is C and AFAIK the standard library does not define a list type. Even if it was C++, it would be perfectly fine if you found yourself using namespaces as what they were designed for. – Jan Mar 25 '15 at 10:58

3 Answers3

2

Seems to work for me:

typedef char *element_t;

typedef
struct {
  element_t *array;     /* start of the array */
  int capacity;         /* number of elements the array */
  int length;           /* used portion of array, 0..capacity */
} list;

int main(int argc, char **argv)
{
    element_t array[2] = {"foo", "bar"};
    list list;
    list.array = array;
    list.capacity = sizeof(array)/sizeof(array[0]);
    list.length = 1;
    printf("%s\n", list.array[0]);
    return 0;
}

You are most likely forgetting to assign list.array to point to a valid array.

juhist
  • 4,210
  • 16
  • 33
  • What if I have a string that I'm going to parse using strtok, and I wish to add those tokens into the array? How would I be able to do that? – bawse Mar 25 '15 at 11:00
  • You need to allocate memory dynamically. Use `strdup(strtok(...))` and remember to check that memory allocation was successful (i.e. didn't return `NULL`) and exit with a clear error message it failed. Remember to also `free()` the memory allocated by `strdup()`. Note that `strdup()` isn't in standard C but it is typically nevertheless supported. `strtok` returns the same buffer every time but replaces the buffer contents which is why you need `strdup()`. – juhist Mar 25 '15 at 11:05
  • What does `strdup(strtok(...))` do? I just googled it but couldn't relate it to this particular situation – bawse Mar 25 '15 at 11:11
  • `strdup()` allocates a new block of memory which is populated with the argument string. So, it essentially saves the string in the memory block used by `strtok()` which will be overwritten later in another `strtok()` call. See http://stackoverflow.com/questions/252782/strdup-what-does-it-do-in-c – juhist Mar 25 '15 at 11:36
  • Why is it necessary to do this? Can't we insert the token into the array right as we obtain it? – bawse Mar 25 '15 at 11:41
  • Well, the token points to a memory buffer that will be reused again the next time `strtok` is called. – juhist Mar 25 '15 at 11:42
1

Change your initialization to:

element_t differentArray[LMAX];
list.array = &differentArray[0];

The rest of your code should work as is after this change. You don't need any further allocations as long as you only keep putting literals like "a" into it.

VoidStar
  • 5,241
  • 1
  • 31
  • 45
1

typedef char *element_t; Don't hide pointers behind typedefs, this is bad practice as it makes the code unreadable. element_t *array will be the same as char** array. Is this actually what you want?

list.array[0] = "a"; suggests that you intended "array" to be an array of pointers? Where do you allocate the actual array? Where do you initialize the struct? list.array[0] is pointing into la-la-land rather than at allocated memory, as far as I can tell from the posted code.

Also, the array of pointers need to be of type const char*, since you are pointing at string literals.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Actually, it is recommended to have the array of pointers as `const char *` when pointing at string literals, but not mandatory: in standard C, string literals are of type `char *` – juhist Mar 25 '15 at 10:59
  • 1
    @juhist Yes, but that is a known "bug" in the C standard. – Lundin Mar 25 '15 at 12:02