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);