在我们的旧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[]
的含义相同。
仍未解决的问题是在什么时候应该使用哪个版本。
答案 0 :(得分:5)
它是一样的。从标准:
在确定每个参数的类型后,将“T的数组”或函数类型T的任何参数调整为“指向T的指针”
所以没有区别。我会使用*
而不是[]
来避免混淆,除非它类似于char* argv[]
,否则它可能会通过。
答案 1 :(得分:1)
以下是K&amp; R 2nd(*)的相关引用,从第99页底部开始:
作为函数定义中的形式参数,
char s[];
和
char *s;
是等价的;我们更喜欢后者,因为它更明确地表示参数是一个指针。当一个数组名称传递给一个函数时,该函数可以方便地相信它已经被数组或指针所占据,并相应地操作它。如果看起来合适且清晰,它甚至可以使用这两种符号。
(*)Kernighan&amp; Ritchie:&#34; C编程语言&#34; (第二版)
答案 2 :(得分:1)
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类型的指针。 希望这会有所帮助。 : - )
答案 3 :(得分:1)
数组和指针不同,但数组和指针的某些属性看起来很相似。
在这种情况下,double * vec和double vec []之间没有区别。
但是无论何时使用数组并使用某些值进行初始化,然后将该数组作为函数参数传递。
在函数签名中,如果你使用double * 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);
}
为什么意味着
- &GT;一旦你分配了你无法释放的内存并动态调整大小,数组就是静态的。
- &GT;这是使用double * vec混淆的一个案例。
- &GT;除了这种情况,两个签名都是相似的。
答案 4 :(得分:-2)
double *vec
意味着vec只指向一个double值。 double []vec
暗示有一系列双打。从你显示的代码看来,双打数组就是你想要的。使用double * vec进行数组操作肯定会导致麻烦。