【问题标题】:How Do you pass a pointer-to-an-array to a function?如何将指向数组的指针传递给函数?
【发布时间】:2012-08-08 09:02:21
【问题描述】:

如何将数组传递给可以编辑其内容的函数?

喜欢做的时候

function(int *x)
 {*x = 10;}

main()
  {int x;
   function(&x);}

如何使用字符数组来做同样的事情?

无论何时

   function(char *array[], int *num)
   { int x = *num;
     *array[x] = 'A'; }

   main()
   { char this[5] = "00000"; //not a string
     int x = 3;
     function(&this, &x); }

DEV C++ 说

[Warning] passing arg 1 of `function' from incompatible pointer type 

显然我做错了什么,所以请告诉我如何解决这个问题。谢谢:D

【问题讨论】:

标签: c arrays pointers parameter-passing


【解决方案1】:

你应该写:

void function(char array[], int *num)
{
   int x = *num;
   array[x] = 'A';
}

void main()
{
   char my_array[5] = "00000";
   int x = 3;
   function(my_array, &x);
}

符号char *array[] 是一个指针数组,此处不需要。

当你在某处传递一个数组时,你不应该获取它的地址。数组默认调整为指针。

编辑:

函数原型:

void function(char array[], int *num);
void function(char *array, int *num);

完全相同。它们之间没有任何细微的差别。

【讨论】:

  • 那么在运行 'function' 之后,main 中的数组的内容会改变吗?
  • 是的,该数组的地址已传递给函数。该函数修改该地址指向的内存。
  • 所以我所做的就像函数 (char **array) 但我只传递 &array??
  • 在 C/C++ 中 array 和 &array 是一回事。这根本不合逻辑,我不喜欢这样,但语言是这样定义的。
【解决方案2】:

由于数组只能通过地址传递,所以这里不需要 char * 数组,只需要一个 char 数组:

rettype function(char *array, int *num)
{
    array[*num] = 'A';
}

int main()
{
    char arr[] = "1234567890";
    int i = 2;
    function(arr, &i);
}

【讨论】:

  • 那么在 main 中运行 'function' arr 后会改变它的内容吗?
【解决方案3】:

在 C 中,数组名称“转移”为指向数组头部的指针,通过传递“&array”,您将传递指向数组头部指针的指针,因此会发出警告。

char array[512];

myfunc(array, foo);

是做你想做的事的正确方法。

【讨论】:

  • " 通过传递“&array”,你传递了一个指向数组头部的指针,因此是警告。” - 这是错误的。获取数组的地址会生成指向数组的指针,而不是指向指向任何数组类型的指针的指针
  • 我不知道“数组”是 C 数据类型。
【解决方案4】:

其实你已经取了一维数组。所以你可以通过两种方式定义函数...

(一)

 function(char array[], int *num)
       { int x = *num;
         *array[x] = 'A'; }

       main()
       { char this[5] = "00000"; //not a string
         int x = 3;
         function(this, &x); }

和

(ii)

function(char *array, int *num)
       { int x = *num;
         *array[x] = 'A'; }

       main()
       { char this[5] = "00000"; //not a string
         int x = 3;
         function(this, &x); }

但是在你的函数定义中,你写了*array[] 作为参数,这意味着数组是二维数组。所以你应该将数组声明为二维数组。

function(char *array[], int *num)
       { int x = *num;
        //implement your code }

       main()
       { char this[5][10];
         // you can initialize this array.
         int x = 3;
         function(this, &x); }

我认为这对你会有帮助。

【讨论】:

    【解决方案5】:

    好的,首先要记住的是,没有“指向数组”的指针之类的东西,尽管您会经常听到这种说法。太草率了。

    (正如下面所指出的,术语“指向数组的指针”确实有严格的含义——但我坚持认为你已经被它弄糊涂了。真正发生的是每个指针都包含一个地址。根据声明,编译器可以识别它是否在上下文中正确使用,这就是您的错误消息真正告诉您的内容:您在函数中声明的是指向字符数组的指针,也就是说同样的事情作为char **,而不是char *,这就是你要传递的。但是char *,或char **,或char ******,重要的是你让它太复杂了——你已经有了你需要的由数组名称标识的地址。)

    指针是指针,它们是地址。

    C 中的数组只是一个分配的内存块,它的名称表示第一个元素的地址。所以

    char a[42];
    

    是一块42个字符长的内存块,a是它的地址。

    你可以将你的第二个函数重写为

    void foo(char* a, int num){ // (3)
         // notice that you don't need the word function and 
         // for lots of reasons I wouldn't use it  as a function name.
         a[num] = 'A'; // (4)
    }
    
    int main(){
          // Sadly "00000" IS a string no matter what your comment
          // says.  Use an array initializer instead.
    
          char arry[5] = {'0','0','0','0','0' } ; // (1)
          foo(arry,3); // (2)
    }
    

    这就是我相信您的代码所要做的事情。请注意

    (1) 由于 "00000" 确实是一个字符串,它实际上是在创建一个数组 6 个元素长,该数组可以使用数组初始化器进行初始化

    {'0','0','0','0','0', 0 }
    

    (2) 数组(我将其命名为 'arry' 而不是 'this',因为 'this' 通常是类 C 语言中的关键字,为什么会有混淆的风险?)已经是一个地址(但 不是 一个指针。它可以在指针赋值的右侧,但不能在左侧。)

    所以当我打电话时

    foo(arry,3);
    

    我用 arry 的第一个元素的地址和数字 3 调用 foo(您不需要为此声明变量。)

    现在,我可以也写成

    foo(&arry[0],3);
    

    您可以将其理解为“找到 arry 的第 0 个元素,获取其地址。”它是 C 中任何数组的标识

    char c[len];
    

    表达式c 和&c[0] 指的是同一个地址。

    (3) 也可以定义为foo(char arry[], int num)。这些是等价的。

    (4) 当您引用a[num] 时,您直接引用了a 指向的内存的第num 个元素,它位于数组@987654340 的开头地址处@。你不需要所有的取消引用。

    不要担心这有点难以理解——每个人开始 C 时都很难。

    【讨论】:

    • “好吧,首先要记住的是,没有“指向数组”的指针之类的东西” - 这是不正确的。肯定有一个指向数组的指针,-1。指向数组的指针:char (*ptoarr)[10]。 ptoarr 是指向 10 个数组 char 的指针。获取数组的地址也会产生一个指向数组的指针。数组是一种成熟的类型,它们不仅仅是伪装的指针。
    • 是的,是的,坚持这种迂腐的做法已经让新手感到困惑 30 年来,i 一直在教 C。但那东西仍然只是一个地址。在这个例子中,感觉他需要一个“指向数组的指针”导致他想到他需要 char * arry[] 而不是 char *。
    • 这不是迂腐,而是语言的工作方式。数组是真正的类型,而不是隐藏的指针。这是一个非常普遍的误解,它只是不需要。另外,说“没有指向数组的指针”是错误的。但是......我认为我在这里制作了足够多的 cmets 来让 OP 意识到这一点。我认为您在编辑后不应该为此投反对票,因此被删除。
    【解决方案6】:

    首先不要使用this作为变量名,它是一个C++关键字。抱歉没有意识到这是一道 C 题。

    main()
    { 
      char foo[5] = "00000"; //not a string
      int x = 3;
      function(foo, &x); 
    }
    

    你不要取foo的内存地址。 foo 在接受指针的上下文中使用时会降级为指向第一个元素的指针。 *foo 与foo[0] 相同,与*(foo + 0) 相同

    同样foo[3] 与*(foo + 3) 相同(编译器负责乘以元素大小)。

    【讨论】:

    • “首先不要将它用作变量名,它是 C++ 关键字。” - 这是一个 C 问题,尽管这可能是一个很好的建议,以防代码有一天会在 C++ 编译器的范围内。但是,foo 强调不是已经是指向第一个元素的指针。它是一个数组。教初学者数组和指针是一回事是一个糟糕的主意,-1。它也与foo[0] 不同。你的意思是&foo[0]?
    • @EdS。直到您发表评论才意识到这是C。当然,我的回答不应该被否决。努力和谨慎会让你投反对票。太棒了。
    • 不,但是说指针和数组是一回事。指针与数组不相同,而且它们从来都不是。这是我在这里看到的最常见的误解之一。正确的答案是,数组在需要时会衰减为指针类型,但它们肯定不是指针。
    • @EdS。好的,我告诉你我忘了在等式解释中提到间接部分。这是一个真正的错误,我现在已经修改了它。
    • Downvote 已删除,尽管这仍然非常具有误导性和不真实性:“因为它已经是指向第一个元素的指针。” 不是 一个指针。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    相关资源
    最近更新 更多