Passing an array of strings as parameter to a function in C Passing an array of strings as parameter to a function in C arrays arrays

Passing an array of strings as parameter to a function in C


The warning is exactly right. Your function wants an array of pointers. You're giving it an array of arrays.

Expected:

 sep_foo: +------+       +-----+ |char**|--> 0: |char*|-->"string1" +------+       +-----+             1: |char*|-->"string2"                +-----+*sep_foo_qty-1: |...  |                +-----+

What you provided:

           sep_foo:           +--------------------------------+        0: | char[MAX_STRING_LENGTH]        |           +--------------------------------+        1: | char[MAX_STRING_LENGTH]        |           +--------------------------------+MAX_QTY-1: | ...                            |           +--------------------------------+

An array with elements of type X can "decay" into a pointer-to-X, or X*. But the value of X isn't allowed to change in that conversion. Only one decay operation is allowed. You'd need it to happen twice. In your case, X is array-of-MAX_STRING_LENGTH-chars. The function wants X to be pointer-to-char. Since those aren't the same, the compiler warns you. I'm a bit surprised it was just a warning since nothing good can come from what the compiler allowed to happen.

In your function, you could write this code:

char* y = NULL;*sep_foo = y;

That's legal code since sep_foo is a char**, so *sep_foo is a char*, and so is y; you can assign them. But with what you tried to do, *sep_foo wouldn't really be a char*; it would be pointing to an array of char. Your code, in effect, would be attempting to do this:

char destination[MAX_STRING_LENGTH];char* y = NULL;destination = y;

You can't assign a pointer into an array, and so the compiler warns that the call is no good.

There are two ways to solve this:

  • Change the way you declare and allocate sep_foo on the calling side so it matches what the function expects to receive:

    char** sep_foo = calloc(MAX_QTY, sizeof(char*));for (int i = 0; i < MAX_QTY; ++i)  sep_foo[i] = malloc(MAX_STRING_LENGTH);

    or, equivalently

    char* sep_foo[MAX_QTY];for (int i = 0; i < MAX_QTY; ++i)  sep_foo[i] = malloc(MAX_STRING_LENGTH);
  • Change the prototype of the function to accept what you're really giving it:

    int parse(const char *foo, char sep_foo[MAX_QTY][MAX_STRING_LENGTH], int *sep_foo_qty);


Parameter 2 should be

char sep_foo[][MAX_STRING_LENGTH]

To clarify, you are passing a pointer to parse() and treating it as a pointer to a pointer. A multidimensional array in C is NOT an array of pointers. It is a single block of memory that is pointed to by the array variable. You cannot dereference it twice.


sep_foo is defined as an array of arrays. In other words, when you use sep_foo, it points to the beginning of sequential memory. Here's a model:

(assume MAX_STRING_LENGTH = 16, MAX_QTY = 2)sep_foo       = &&0000sep_foo[0]    =  &0000sep_foo[0][0] = *&0000 = 12sep_foo[0][8] = *&0008 = 74sep_foo[1]    =  &0010sep_foo[1][0] = *&0010 = 120000  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE0010  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE

However, your function expects an array of pointers (actually, a pointer to a pointer). This is modeled as such:

sep_foo_arg       =   &&0000sep_foo_arg[0]    =  *&&0000 = &0010sep_foo_arg[0][0] =  *&*&0000 = 12sep_foo_arg[0][8] = *(&*&0000 + 8) = 74sep_foo_arg[1]    =  *&&0002 = &0020sep_foo_arg[1][0] = *&*&0000 = 120000  0010 0020  xxxx xxxx  xxxx xxxx  xxxx xxxx0010  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE0020  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE

Yeah ... Syntax may be a bit confusing for my explanations...

Anyway, you can solve this issue by telling your function how to treat the pointer pointed to. In particular, you would want to treat it as an array (a sequence of memory):

int parse(const char *foo, char (*sep_foo)[MAX_STRING_LENGTH], int *sep_foo_qty);