更新时间:2022-11-12 16:29:38
警告完全正确.您的函数需要一个指针数组.你给它一个数组数组.
预期:
sep_foo:+------+ +-----+|char**|--> 0: |char*|-->"string1"+------+ +-----+1: |char*|-->"string2"+-----+*sep_foo_qty-1: |... |+-----+您提供的内容:
sep_foo:+--------------------------------+0: |字符[MAX_STRING_LENGTH] |+--------------------------------+1: |字符[MAX_STRING_LENGTH] |+--------------------------------+MAX_QTY-1: |... |+--------------------------------+具有X
类型元素的数组可以衰减"为指向X
或X*
的指针.但是 X
的值在那个转换中是不允许改变的.只允许一个衰减操作.你需要它发生两次.在您的情况下, X
是 MAX_STRING_LENGTH
字符数组.该函数希望 X
成为指向字符的指针.由于这些不一样,编译器会警告您.我有点惊讶这只是一个警告,因为编译器允许发生的事情不会带来任何好处.
在您的函数中,您可以编写以下代码:
char* y = NULL;*sep_foo = y;
这是合法的代码,因为 sep_foo
是一个 char**
,所以 *sep_foo
是一个 char*
,y
也是如此;你可以分配它们.但是根据您的尝试,*sep_foo
不会真的成为char*
;它将指向一个字符数组.实际上,您的代码将尝试执行此操作:
字符目标[MAX_STRING_LENGTH];字符* y = NULL;目的地 = y;
您不能将指针分配到数组中,因此编译器警告该调用无效.
有两种方法可以解决这个问题:
改变你在调用方声明和分配 sep_foo
的方式,使其与函数期望接收的内容相匹配:
char** sep_foo = calloc(MAX_QTY, sizeof(char*));for (int i = 0; i
或者,等效地
char* sep_foo[MAX_QTY];for (int i = 0; i
改变函数的原型以接受你真正给它的东西:
int parse(const char *foo, char sep_foo[MAX_QTY][MAX_STRING_LENGTH], int *sep_foo_qty);
I want a simple function that receives a string and returns an array of strings after some parsing. So, this is my function signature:
int parse(const char *foo, char **sep_foo, int *sep_foo_qty) {
int i;
char *token;
...
strcpy(sep_foo[i], token); /* sf here */
...
}
Then I call it like this:
char sep_foo[MAX_QTY][MAX_STRING_LENGTH];
char foo[MAX_STRING_LENGTH];
int sep_foo_qty, error;
...
error = parse(foo, sep_foo, &sep_foo_qyt);
...
This way I get a warning during compilation:
warning: passing argument 2 of 'parse' from incompatible pointer type
And then a segmentation fault during execution in the line marked with /* sf here */
What is wrong in my C code?
Thanks in advance
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);