我想要一个接收字符串的简单函数,并在解析后返回一个字符串数组。所以,这是我的功能签名:
int parse(const char *foo, char **sep_foo, int *sep_foo_qty) {
int i;
char *token;
...
strcpy(sep_foo[i], token); /* sf here */
...
}
然后我称之为:
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);
...
这样我在编译时会收到警告:
warning: passing argument 2 of 'parse' from incompatible pointer type
然后在/ * sf标记为* /
的行中执行期间出现分段错误我的C代码有什么问题?
提前致谢
答案 0 :(得分:28)
警告完全正确。你的函数想要一个指针数组。你给它一个数组数组。
预期:
sep_foo: +------+ +-----+ |char**|--> 0: |char*|-->"string1" +------+ +-----+ 1: |char*|-->"string2" +-----+ *sep_foo_qty-1: |... | +-----+
您提供的内容:
sep_foo: +--------------------------------+ 0: | char[MAX_STRING_LENGTH] | +--------------------------------+ 1: | char[MAX_STRING_LENGTH] | +--------------------------------+ MAX_QTY-1: | ... | +--------------------------------+
包含X
类型元素的数组可以“衰减”为指针指向X
或X*
。但是X
的值不允许在该转换中更改。仅允许一次衰减操作。你需要它发生两次。在您的情况下,X
是数组 - MAX_STRING_LENGTH
- 字符。该函数希望X
成为指向char的指针。由于它们不相同,编译器会发出警告。我有点惊讶它只是一个警告,因为编译器允许发生的事情没有任何好处。
在您的函数中,您可以编写以下代码:
char* y = NULL;
*sep_foo = y;
这是合法代码,因为sep_foo
是char**
,因此*sep_foo
是char*
,y
也是如此。你可以分配它们。但是,根据您的尝试,*sep_foo
<{1}}它会指向一个char数组。实际上,您的代码将尝试执行此操作:
char*
您无法将指针分配到数组中,因此编译器会警告该调用不合适。
有两种方法可以解决这个问题:
更改您在主叫方声明和分配char destination[MAX_STRING_LENGTH];
char* y = NULL;
destination = y;
的方式,使其与函数预期接收的内容相匹配:
sep_foo
或等同于
char** sep_foo = calloc(MAX_QTY, sizeof(char*));
for (int i = 0; i < MAX_QTY; ++i)
sep_foo[i] = malloc(MAX_STRING_LENGTH);
更改函数的原型以接受您真正给出的内容:
char* sep_foo[MAX_QTY];
for (int i = 0; i < MAX_QTY; ++i)
sep_foo[i] = malloc(MAX_STRING_LENGTH);
答案 1 :(得分:15)
参数2应为
char sep_foo[][MAX_STRING_LENGTH]
为了澄清,您正在传递一个指向parse()的指针并将其视为指向指针的指针。 C中的多维数组不是指针数组。它是数组变量指向的单个内存块。你不能两次取消引用它。
答案 2 :(得分:4)
sep_foo
被定义为数组数组。换句话说,当您使用sep_foo
时,它指向顺序内存的开头。这是一个模型:
(assume MAX_STRING_LENGTH = 16, MAX_QTY = 2)
sep_foo = &&0000
sep_foo[0] = &0000
sep_foo[0][0] = *&0000 = 12
sep_foo[0][8] = *&0008 = 74
sep_foo[1] = &0010
sep_foo[1][0] = *&0010 = 12
0000 12 34 56 78 9A BC DE F0 74 10 25 89 63 AC DB FE
0010 12 34 56 78 9A BC DE F0 74 10 25 89 63 AC DB FE
但是,您的函数需要一个指针数组(实际上是一个指向指针的指针)。这是建模的:
sep_foo_arg = &&0000
sep_foo_arg[0] = *&&0000 = &0010
sep_foo_arg[0][0] = *&*&0000 = 12
sep_foo_arg[0][8] = *(&*&0000 + 8) = 74
sep_foo_arg[1] = *&&0002 = &0020
sep_foo_arg[1][0] = *&*&0000 = 12
0000 0010 0020 xxxx xxxx xxxx xxxx xxxx xxxx
0010 12 34 56 78 9A BC DE F0 74 10 25 89 63 AC DB FE
0020 12 34 56 78 9A BC DE F0 74 10 25 89 63 AC DB FE
是的......语法对我的解释可能有点混乱......
无论如何,你可以通过告诉你的函数如何处理指向的指针来解决这个问题。特别是,您可能希望将其视为一个数组(一系列内存):
int parse(const char *foo, char (*sep_foo)[MAX_STRING_LENGTH], int *sep_foo_qty);
答案 3 :(得分:-2)
如果那是您的确切代码,那么我猜测段错误是因为您没有为解析函数中的char* token
分配内存,然后在strcpy中使用它。< / p>