我想要一个简单的函数,它接收一个字符串并在一些解析后返回一个字符串数组.所以,这是我的功能签名:
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代码有什么问题?
提前致谢
警告是完全正确的.你的函数想要一个指针数组.你给它一个数组数组.
预期:
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
不会真的是一个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);
更改函数的原型以接受您真正给出的内容:
int parse(const char *foo, char sep_foo[MAX_QTY][MAX_STRING_LENGTH], int *sep_foo_qty);
参数2应该是
char sep_foo[][MAX_STRING_LENGTH]
为了澄清,您传递一个指向parse()的指针并将其视为指向指针的指针.C中的多维数组不是指针数组.它是数组变量指向的单个内存块.你不能两次取消引用它.