views:

45

answers:

3

Suppose I have the following code:

typedef struct
{
    char **p;
} STRUCT;

int main()
{
    STRUCT s;
    *(s.p) = "hello";
    printf("%s\n", *(s.p));

    return 0;
}

which obviously doesn't work, but it should show what I want to do. How would I go about initialising, accessing, printing, etc the array of strings in the structure?

+3  A: 

You have two * where you want just one, I think. Try:

typedef struct
{
    char *p;
} STRUCT;

int main()
{
    STRUCT s;
    s.p = "hello";
    printf("%s\n", s.p);

    return 0;
}

If you do really want to have the double indirection, you need to allocate some space for the pointer you're dereferencing. *(s.p) in your original program dereferences an uninitialized pointer. In this case:

typedef struct
{
    char **p;
} STRUCT;

int main()
{
    STRUCT s;
    s.p = malloc(sizeof(char *));
    *(s.p) = "hello";
    printf("%s\n", *(s.p));
    free(s.p);
    return 0;
}

This second program allocates space for just one string pointer; if you want an array, just allocate the appropriate amount of space.

Carl Norum
+2  A: 

There is no array at the moment, but I assume you want to create one. You need to first allocate as many char *s as you want strings:

int main()
{
    STRUCT s;
    int N = 10; // number of strings you want
    s.p = (char **)malloc(N * sizeof(char *));
    s.p[0] = "hello";
    s.p[1] = "world";
    ...
    printf("%s\n", s.p[0]);
    free(s.p);

    return 0;
}
casablanca
Hmmm but can a pointer not be considered an array as well? ie. with `char** p`, the first pointer points to a string and the second one points to the characters in the string.
jon2512chua
@jon2512chua: An array can be considered as a pointer, not the other way round. You can't store anything using a pointer unless you allocate space for it, or make it point to an existing variable/array.
casablanca
Ok got it thanks.
jon2512chua
A: 

You're going to need to know how many strings are contained in the array, either by adding a count member to the struct or by using a NULL sentinel value. The following examples use the NULL sentinel:

Allocating and initializing:

STRUCT s;
s.p = malloc(sizeof *s.p * (number_of_strings + 1));
if (s.p)
{
  size_t i;
  for (i = 0; i < number_of_strings; i++)
  {
    s.p[i] = malloc(length_of_ith_string + 1);
    if (s.p[i])
      strcpy(s.p[i], ith_string);
  }
  s.p[i] = NULL;
}

for appropriate values of number_of_strings, length_of_ith_string, and ith_string.

Accessing/printing:

for (i = 0; s.p[i] != NULL; i++)
  printf("String %d: %s\n", i, s.p[i]);

Deallocating:

for (i = 0; s.[i] != NULL; i++)
  free(s.p[i]);
free(s.p);
John Bode