这是什么语法double x[]
?
它是声明数组的C方式吗?
如果我有类似的功能
void evaluate(double x[], double *f)
{
// evaluate
}
我可以传递任意长度的参数 x 吗?
数组类型的参数的行为与指针完全相同。您不能真正将数组作为函数参数传递。但是,这种语法给人一种错觉,即为了便于阅读,您可以这样做。所以你的功能相当于:
void evaluate(double *x, double *f)
{
// evaluate
}
从 ISO/IEC 14882:2011 的 §8.3.5/5 开始:
在确定每个参数的类型后,将“T的数组”或“返回T的函数”类型的任何参数分别调整为“指向T的指针”或“返回T的函数的指针”。
表示数组的表达式将衰减为指向其第一个元素的指针,因此您仍然可以这样做:
void evaluate(double x[]);
int array[] = {1, 2, 3, 4, 5};
evaluate(array); // The array decays to a pointer to its first element
从§4.2:
“NT 数组”或“T 的未知边界数组”类型的左值或右值可以转换为“指向 T 的指针”类型的纯右值。结果是指向数组第一个元素的指针。
所以是的,您确实可以传递任意长度的数组。实际上,您只是传递一个指向第一个元素的指针。但是,如果需要,您还需要传递数组的长度。
数组可能会令人困惑,因为在大多数情况下,数组的名称会衰减为指向其第一个元素的指针。所以:
double x[3]; // x is an array of 3 doubles
void f(double x[3]); // f takes a pointer to double
f(x); // calls f with the address of x[0]
将数组类型衰减为指针的原因f
是,您不必为每个数组大小都有一个单独的函数:
double x[3];
double y[4];
void f(double x[3], int size) {
for (int i = 0; i < size; ++i)
std::cout << x[i] << ' ';
std::cout << '\n';
}
f(x, 3);
f(y, 4);
如果参数是double*x
, double x[]
, double x[3]
, double x[17]
, double x[]
;它的工作方式相同 在所有这些情况下,x
都被视为double*
。
在函数的参数列表中,double x[]
与double *x
.
我可以传递任意长度的参数 x 吗?
是的,你可以通过。但是没有办法知道x
函数中数组的长度evaluate
。所以你可能也想传递长度。
由于数组立即衰减为指针,因此数组从未真正传递给函数。您可以假设一个函数接收一个数组作为参数,并通过将相应的参数声明为数组来说明它:
void f(char a[]) { ... }
从字面上解释,这个声明没有用,所以编译器转过身来假装你写了一个指针声明,因为这是函数实际上会收到的:
void f(char *a) { ... }
如果函数传统上用于对数组进行操作,或者如果参数在函数中自然地被视为数组,那么将函数称为“接收”数组并没有什么特别的错误。
这种将类似数组的声明符转换为指针的方法仅适用于函数形式参数声明,其他任何地方都没有。如果转换困扰您,您不会被迫使用它;许多程序员得出的结论是,它造成的混乱超过了声明“看起来像”函数内的调用或使用的小优势。(请注意,转换只发生一次;类似 char a2[][] 的东西不起作用。请参阅问题 6.18 和 6.19。)
换句话说,在函数参数声明中,未指定长度的数组与指针相同。
void evaluate(double x[], double *f)
{
// evaluate
}
实际上相当于:
void evaluate(double *x, double *f)
{
// evaluate
}
在 C 和 C++ 中。
这意味着x
参数的类型double *
在这两种情况下都是。
您的函数的参数x
是一个未指定长度的数组。这意味着您可以将任何类型的数组传递double
给它,无论大小。您还可以将指向 a 的指针作为double
参数传递。
但是有一个警告:您不能sizeof
在数组上使用运算符x
,因为它没有大小。