【问题标题】:Pass by reference String array to function and modify content in C通过引用字符串数组传递函数和修改 C 中的内容
【发布时间】:2012-11-01 00:09:22
【问题描述】:

我在这里做错了什么,将 char 数组传递给函数并在函数中提供每个索引内存(使用 malloc()),然后使用 gets() 从键盘插入一些东西。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

void test(char *arr[]);
int main(){
  char *arr[2];//2 is the rows
 /* arr[0] = malloc(80);//This commented code works
  arr[1] = malloc(80);
  strcpy(arr[0], "hey");
  strcpy(arr[1], "whats up");
*/

  test(*arr);
  printf("in array[0]: %s", arr[0]);
  printf("in array[1]: %s", arr[1]);
  return 0;
}
void test(char *arr[]){
  int index;
  char *input = malloc(80);
  for(index = 0; index < 2; index++){
  arr[index] = malloc(80);
  gets(input);
  strcpy(arr[index], input);
  //arr[0] = input;
  }
}

只是一个非常基本的程序,由于某种原因我遇到了麻烦。还有一个问题当我声明一个数组时,这些表单之间有什么区别

char *array

反对

char *array[size]

char **array

谢谢, 凯文

【问题讨论】:

    标签: c arrays pointers char


    【解决方案1】:

    您将arr 声明为char *arr[2]。然后传入*arr,它的类型为char* 进行测试。但是测试需要char *[]。所以这行不通。您应该直接传入arr,即test(arr)

    char * array 是一个指向字符的指针,通常用于指向字符数组(即字符串)中的第一个字符。 char **array 是一个指向字符的指针。通常用于表示字符串数组。 char *array[size] 与上面的基本等价,但与上面的不同,顶层指针已经指向一个有效的数组,因此该数组不需要是malloced。

    顺便说一句,您的test 函数可以简化一点:strcopy 是不必要的。

    void test(char *arr[])
    {
        int i;
        for(i=0;i<2;i++)
        {
            arr[i] = malloc(80);
            gets(arr[i]);
        }
    }
    

    【讨论】:

      【解决方案2】:

      好的,在 C 声明中,您只会获得从声明中读取的第一个分配的内容。

      在您了解如何阅读声明之前,这有点晦涩。

      运算符具有优先级,并且该优先级适用于声明。为简单起见,采取:

      () - Either raises precedence, or means "function taking parameters and returning..."
      [] - Array of
      * - Pointer to (right associative)
      

      所以,声明:

      char *a[3];
      

      是“3 个指向 char 的指针的数组”,而

      char (*a)[3];
      

      是“指向 3 个字符数组的指针”(指向行宽为 3 的多维字符数组行的指针)

      编译器分配堆栈上的第一件事。因此,在第一个示例中,您获得了三个能够指向(尚未分配的)字符的指针。

      | ptr | --> (unallocated char)
      | ptr | --> (unalloc char)
      | ptr | --> (unalloc char)
      

      在第二个:

      | ptr | --> (unallocated block of 3 char)
      

      下一条规则是:如果你有一个指针,你就有一个数组。所以在这两种情况下,你都会得到多维数组。

      首先,行数是固定的(您已经分配了它),但每一行可以有不同的大小,因为编译器知道指针可以偏移一个字符以到达下一个字符。

      第二个,你有一个固定的行大小,但编译器知道如何偏移你的基指针(每个 3 个字符),所以你有任意数量的行。

      C 也是一种按值调用的语言。所以,如果你声明了一个变量:

      char *a[3];
      

      那么 'a' 本身就是“一个 3 ptr 到 char 的数组”,但 a[0] 是“一个 ptr 到一个 char”,而 a[0][0] 是一个 char。

      当你编写一个期望的函数时:

      void f(char *arg[]) {
      ...
      }
      

      您必须将一个指向 char 的指针数组传递给它。它不关心有多少行(你必须跟踪它)......它只关心类型是否正确。

      因此,如果您像我们的第一个示例中那样声明了“a”,则必须调用 f(a)。函数调用对函数 args 执行类似赋值的操作:

      f(a) 表示用 (arg = a) 调用 f。

      优先规则特别重要,你应该在这些规则上工作,直到你能阅读这样的声明:

      int (*f(int (*a)[4], void (*f)()))[6];
      
      which is "f is a function that takes:
        - a pointer to arrays of 4 int
        - a pointer to a function that takes nothing and returns nothing)
      and (then f) returns a pointer to arrays of 6 int".
      

      【讨论】:

        【解决方案3】:

        char *array 创建一个指向内存字节的指针。 char *array[size] 创建一个指向长度为“size”的数组的指针。 char **array 只是一个指向内存字节指针的指针

        如您所见,您的代码的问题在于您正试图通过测试函数,这是它没有预料到的。测试函数想要一个指向指针的指针,你只需给它一个指针。正确的段落应该是: 测试(arr);

        从第二个角度来看:你在制作命令行程序时会看到这一点(有点)。

        考虑以下代码:

        #include<stdio.h>
        
        int main(int argc, char *argv[]) {
            printf("%s\n", argv[0]);
            return 0;
        }
        

        argv 指针指向命令行参数,每个参数都是一个字符串(它只是一个指针,或者是一个数组)。因此,假设您为 Linux 执行了以下操作:

        ./some_program -option opt-input

        每个都被视为自己的字符串。 char *argv[] 指向每个字符串。第一个 printf 会打印出 ./some_program,因为这是 argv 指向的第一个字符串。

        【讨论】:

          猜你喜欢
          • 2021-12-04
          • 2015-04-04
          • 1970-01-01
          • 2011-07-08
          • 1970-01-01
          • 2018-09-01
          • 1970-01-01
          • 2015-05-19
          • 2016-10-26
          相关资源
          最近更新 更多