简体   繁体   English

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

[英]Passing an array of strings as parameter to a function in C

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 */ 然后在标记为/ * sf的行中执行期间出现分段错误* /

What is wrong in my C code? 我的C代码有什么问题?

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* . 具有X类型元素的数组可以“衰减”为指向XX*的指针。 But the value of X isn't allowed to change in that conversion. 但是X的值不允许在该转换中发生变化。 Only one decay operation is allowed. 只允许一次衰减操作。 You'd need it to happen twice. 你需要它发生两次。 In your case, X is array-of- MAX_STRING_LENGTH -chars. 在您的情况下, XMAX_STRING_LENGTH -chars数组。 The function wants X to be pointer-to-char. 该函数希望X成为指向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 ; 这是合法代码,因为sep_foo是一个char** ,所以*sep_foo是一个char* ,所以是y ; you can assign them. 你可以分配它们。 But with what you tried to do, *sep_foo wouldn't really be a char* ; 但是你试图做的事情, *sep_foo 真的不是一个char* ; it would be pointing to an array of char. 它会指向一个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: 更改您在调用端声明和分配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); 

    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 参数2应该是

char sep_foo[][MAX_STRING_LENGTH]

To clarify, you are passing a pointer to parse() and treating it as a pointer to a pointer. 为了澄清,您传递一个指向parse()的指针并将其视为指向指针的指针。 A multidimensional array in C is NOT an array of pointers. C中的多维数组不是指针数组。 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. sep_foo被定义为数组数组。 In other words, when you use sep_foo , it points to the beginning of sequential memory. 换句话说,当你使用sep_foo ,它指向顺序内存的开头。 Here's a model: 这是一个模型:

(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

However, your function expects an array of pointers (actually, a pointer to a pointer). 但是,您的函数需要一个指针数组(实际上是指向指针的指针)。 This is modeled as such: 这是建模的:

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM