代码之家  ›  专栏  ›  技术社区  ›  mmutilva

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

  •  14
  • mmutilva  · 技术社区  · 17 年前

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

    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代码有什么问题?

    提前谢谢

    4 回复  |  直到 17 年前
        1
  •  28
  •   Rob Kennedy    17 年前

    警告完全正确。函数需要一个指针数组。你给它一个数组。

     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 -查斯。函数需要 成为指向char的指针。因为它们不一样,编译器会警告您。我有点惊讶,这只是一个警告,因为编译器允许发生的事情不会带来任何好处。

    在函数中,您可以编写以下代码:

    char* y = NULL;
    *sep_foo = y;
    

    那是法律法规 sep_foo char** *sep_foo 是一个 char* y *塞普富 不会 做一个

    char destination[MAX_STRING_LENGTH];
    char* y = NULL;
    destination = y;
    

    您无法将指针分配到数组中,因此编译器会警告该调用无效。

    有两种方法可以解决此问题:

    • 更改声明和分配的方式 塞普富

      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
  •  15
  •   codelogic    17 年前

    参数2应为

    char sep_foo[][MAX_STRING_LENGTH]
    

    为了澄清这一点,您将向parse()传递一个指针,并将其视为指向指针的指针。C中的多维数组不是指针数组。它是数组变量指向的单个内存块。您不能取消引用它两次。

        3
  •  4
  •   strager    17 年前

    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);
    
        4
  •  -2
  •   sykora    17 年前

    如果这是您的确切代码,那么我猜SEGFULT是因为您没有将内存分配给 char* token