【问题标题】:Differences between double *vec and double vec[]double *vec 和 double vec[] 的区别
【发布时间】:2016-06-02 04:47:29
【问题描述】:

在我们遗留的 C/C++ 代码中,我遇到了两个版本的签名

void foo1(double *vec, int n)

和

void foo2(double vec[], int n)

但是在方法内部对参数vec的处理没有区别例如:

void foo2(double vec[], int n){
    for(int i=0;i<n;i++)
      do_something(vec[i]);
}

第一个版本 (double *) 和第二个版本 (double ..[]) 有什么区别吗?在什么情况下应该优先选择一个版本?

编辑:在@Khaled.K 的提示之后,我尝试编译:

void foo(double *d, int n){}
void foo(double d[], int n){}

由于重新定义 void foo(double *d, int n) 而出现编译错误。所以double *vec 和double vec[] 的意思是一样的。

仍然悬而未决的问题是何时应该使用哪个版本。

【问题讨论】:

  • 不,没有区别。在一个参数中[]被调整为*。
  • @LưuVĩnhPhúc,他希望在将它们作为参数传递给函数时有所不同。
  • 代码中的同一个函数是否存在两个签名?
  • @Khaled.K 不,有两种签名,用于不同的功能。谢谢,我调整了我的问题

标签: c++ c


【解决方案1】:

都是一样的。来自标准:

确定每个参数的类型后,将任何类型为“T的数组”或函数类型为T的参数调整为“指向T的指针”

所以没有区别。我会使用* 而不是[] 以避免混淆,除非它类似于char* argv[],否则它可能是可以通过的。

【讨论】:

  • 我会说使用两者来更好地记录参数的意图:* 当函数期望参数是单个项目时,[] 当它期望它是多个项目时。
  • 我不明白你最后一句是什么意思。你能详细说明一下吗?
  • @user694733 想说void foo2(double *) "可能有帮助" 来破译传递了一个双精度变量,因为 double * 的简单含义只是一个指向双精度的指针或存储双精度的地址。 void foo2(double []) 可能有助于破译 foo2 内部传递的双精度数组。
【解决方案2】:

这是来自 K&R 2nd (*) 的相关引述,从第 99 页底部开始:

作为函数定义中的形参,

char s[];

和

char *s;

是等价的;我们更喜欢后者,因为它更明确地说参数是一个指针。当一个数组名被传递给一个函数时,该函数可以在方便的时候相信它是一个数组或一个指针,并相应地操作它。如果它看起来合适且清晰,它甚至可以使用这两种符号。

(*) Kernighan & Ritchie:“C 编程语言”(第二版)

【讨论】:

    【解决方案3】:

    c 中没有绑定检查。如您所知,数组名称本身充当指针(具有特殊属性)。每当您将数组作为参数传递给函数时,它将在内部作为相应类型的指针传递。这就是为什么如果你想对绑定检查进行一些操作,你还需要传递数组的长度。编译器为指针和数组生成相同的签名(目标代码)作为形式参数。您可以根据自己的选择使用这两个变量。 下面是一个简单的例子:

    #include <iostream>
    void arrayParamTest(int arr[])
    {
    }
    int main()
    {
        int arr[] = {10, 20};
        arrayParamTest(arr);
    }
    

    现在编译它,让我们看看符号:

    techie@gateway2:myExperiments$ nm a.out | grep "arrayParamTest"
    00000000004006e7 t _GLOBAL__I__Z14arrayParamTestPi
    0000000000400674 T _Z14arrayParamTestPi 
    

    请参阅编译器生成带有“Pi”作为参数的符号。 Pi 表示 int 类型的指针。 希望这会有所帮助。 :-)

    【讨论】:

      【解决方案4】:

      数组和指针不同,但数组和指针的某些属性看起来很相似。

      在这种情况下,double *vec 和 double vec[] 没有区别。

      但是,每当您获取数组并使用一些值进行初始化,然后将该数组作为函数参数传递时。

      在函数签名中,如果你使用双 *vec,那么你会意外地尝试在函数定义中动态释放该内存,然后它将在运行时抛出异常,即这可能是由于堆损坏。

      示例:

      #include<stdio.h>
      #include<stdlib.h>
      void foo1(int *arr);
      int main()
      {
          int arr[] = {10, 20};
          foo1(arr);
      
          return 0;
      }
      void foo1(int *arr)
      {
          printf("in array\n");
          free(arr);
      }
      

      为什么意味着

      --> 数组本质上是静态的,一旦分配了内存,就无法动态释放和调整大小。

      --> 这是使用双 *vec 混淆的一种情况。

      --> 除了这种情况,两个签名都是相似的。

      【讨论】:

        【解决方案5】:

        double *vec 意味着只有一个由 vec 指向的 double 值。 double []vec 暗示有一个双精度数组。从您显示的代码看来,双打数组是您想要的。使用 double *vec 进行数组操作势必会带来麻烦。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-07
          • 1970-01-01
          • 1970-01-01
          • 2018-04-17
          • 2022-08-07
          相关资源
          最近更新 更多