将一个字符串数组作为参数传递给C中的函数

我想要一个简单的函数,它接收一个字符串并在一些解析后返回一个字符串数组。 所以,这是我的function签名:

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类型元素的数组可以“衰减”为指向XX*的指针。 但是X的值不允许在该转换中发生变化。 只允许一次衰减操作。 你需要它发生两次。 在您的情况下, XMAX_STRING_LENGTH -chars数组。 该函数希望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中的多维数组不是指针数组。 它是由数组变量指向的单个内存块。 你不能两次取消引用它。

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

如果这是你的确切代码,那么我猜测segfault是因为你没有为你的解析函数中的char* token分配内存,然后在你的strcpy中使用它。