【问题标题】:C pointer notation compared to array notation: When passing to functionC 指针表示法与数组表示法的比较:传递给函数时
【发布时间】:2012-12-27 06:18:09
【问题描述】:

我的问题基于以下代码:

int myfunct(int ary[], int arysize)   
int myfunct2(int *ary, int arysize)

 int main(void){
   int numary[10];
   myfunct(numary, 10)
   myfunct2(numary, 10)
   return;
 }

int myfunct(int ary[], int arysize) {   
      //Whatever work is done

  }

int myfunct2(int *ary, int arysize) {
     // Whatever work is done

  }

是否有理由使用其中一个而不是另一个?详细地说,当涉及数值数组时,是否有任何理由要使用指针表示法而不是数组表示法。如果使用指针表示法,则将在函数中使用指针算术等。如果使用 [] 数组表示法,则可以像往常一样使用数组。我是编程新手,目前我认为使用指针表示法没有任何好处。

我的确切问题是,是否有任何理由使用指针表示法将数值数组传递给函数,因此在函数内使用指针操作。

【问题讨论】:

    标签: c arrays function pointers


    【解决方案1】:

    这两种符号在功能上没有真正的区别。在 C 中,当您将数组变量传递给函数时,它会衰减为指针,而不管表示法如何。但是,在我看来,指针表示法更可取。函数定义中[] 符号的问题在于,在我看来,它有些误导:

    void foo(int array[])
    {
    
    }
    

    新手 C 程序员普遍存在的一个错误是假设 sizeof(array) 将得到数组中元素的数量乘以 sizeof(int),就像 array 是一个数组一样在栈上声明的变量。但现实情况是array 已衰减为一个指针,尽管是具有误导性的[] 符号,因此sizeof(array) 将变为sizeof(int*)array 实际上只是一个指向第一个元素的指针,或者可能是一个指向在任何地方分配的单个整数的指针。

    例如,我们可以这样调用foo

    int x = 10;
    foo(&x);
    

    在这种情况下,foo 定义中的 [] 符号有点误导。

    【讨论】:

    • 那么如果我使用 *ary 来反对 ary[],我可以在函数中使用 ary[0] 吗?
    • @Vlad 我以为你明白我的回答? ary[0]*(ary + 0)*ary,无论上下文如何。如果你可以使用一个,你可以使用另一个(即在表达式中)。
    • “在 C 中,当你将数组变量传递给函数时,它会衰减为指针,而不管符号如何。”不会。数组衰减为指针因为函数采用指针参数。 “新手 C 程序员普遍存在的一个错误是假设 sizeof(array) 将为您提供数组中元素的数量乘以 sizeof(int)”。不,如果array 是数组类型,那么sizeof(array) 总是给你元素的数量乘以组件类型的大小。但是这里array 不是数组;它有指针类型(int *)。
    • 在说什么? “数组衰减为指针,因为函数采用指针参数”与说“当您将数组变量传递给函数时,它衰减为指针”是一样的。一个函数现在不能很好地接受一个数组参数吗?
    【解决方案2】:

    当您将函数参数声明为数组时,编译器会自动忽略数组大小(如果有)并将其转换为指针。也就是这个声明:

    int foo(char p[123]);
    

    100% 等同于:

    int foo(char *p);
    

    事实上,这不是关于符号,而是关于实际类型:

    typedef char array_t[42];
    int foo(array_t p);  // still the same function
    

    这与您如何在函数中访问p 无关。此外,[] 运算符不是“数组表示法”。 [] 是指针运算符:

    a[b]
    

    100% 等同于:

    *(a + b)
    

    【讨论】:

    • 我明白这一点。我的问题是指将在该函数中进行的操作。
    • @Vlad 如果你的问题是关于函数的内部,为什么你的示例代码除了那个之外什么都有?
    【解决方案3】:

    您只需要对多维数组使用数组表示法。 (您不必提供第一个维度的大小)。

    【讨论】:

    • 我们也可以使用指针表示法将指针传递给多维数组。
    • @RobertSsupportsMonicaCellio 好吧,也许对于第一个维度,但无论如何您仍然需要对其余维度使用数组表示法。
    【解决方案4】:

    这些声明是完全相同的。引用标准:

    将参数声明为“类型数组”应调整为 “限定类型的指针”

    C99 标准第 6.7.5.3 节第 7 段

    【讨论】:

      【解决方案5】:

      我认为,在自 C99 以来具有可变长度数组的现代 C 语言中,如果是数组,数组表示法更可取。对于一维数组,你可以这样做

      int myfunct(size_t size, int array[size]) {
        ... array[i] ..
      }
      

      对于二维

      int myfunct(size_t size, int array[size][size]) {
        ... array[i][j] ..
      }
      

      所以数组表示法更适合一般情况。一个复杂的编译器甚至可以进行边界检查,但我还不知道有什么这样做的。

      【讨论】:

      • 请注意,在一维情况下,int array[size] 仍然与int *array 具有相同的效果,即array 仍然是一个指针,而size 是多余的,除了用作文档。在二维情况下,array 的类型是 int (*)[size]
      【解决方案6】:

      在我看来,在函数原型中更喜欢指针表示法而不是空数组表示法的主要原因是后者与结构定义不一致:

      struct person {
         char *firstname;
         char *lastname;
      };
      
      void setperson(struct person *p, char firstname[], char lastname[])
      {
          p->firstname = firstname;
          p->lastname = lastname;
      }
      

      在结构中,无论如何您都必须使用指针表示法,因为空数组表示法仅对最后一个成员有效,至少从 C99 开始,当您想将其设为 flexible array member 时。

      【讨论】:

      • 你的帖子完全放错地方了。一件事与另一件事无关。 *arrarr[] 在 C 中除函数参数列表之外的任何其他位置之间存在差异是显而易见的,并且与此问题无关。它甚至可能会混淆某些人,他们来这里是为了在 parameters 处获得这个符号的答案。我站在你这边,指针表示法更好,但它实际上与结构定义没有任何关系。 -1
      • 这篇文章指出,当显然想要传递指针时,使用数组表示法是没有意义的。但它非常令人困惑,并且与函数定义或链表无关,特别是当您关注时。
      猜你喜欢
      • 2011-07-16
      • 2022-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 1970-01-01
      • 2019-02-05
      相关资源
      最近更新 更多