函数采用预期大小的数组,向用户发出信号

Function takes array of expected size, signalizing that to user

本文关键字:用户 信号 数组 函数      更新时间:2023-10-16

将函数声明为合法吗

void f (T arr[10]); // T is built-in type or class

向用户发出信号,告知其期望大小为10的数组?还是风格不好?

我知道传递数组总是通过指针来处理的,但最好让函数的用户知道——只需查看声明——传递的数组必须具有指定的大小,而用户不必阅读函数的整个文档。

将是

void f (T arr[10] = 0)
{
if (!arr)
// do stuff without array
else
// do stuff with array
}

也可以吗?f()也可在不传递数组的情况下使用(默认参数0)。

如果你真的只期望10个元素的C风格数组,

void f( int (&array)[10] );

将强制执行;任何试图传递除int [10]以外的任何内容的行为将无法编译。

这方面的问题是:

  • 如果调用者自己已经接收到数组作为参数,他没有遵守这个惯例,他不能给你打电话。你不能用指针调用此函数。

  • 如果调用者有一个较大的数组,并且只希望您访问一个10元素的子数组,他不能给你打电话。

根据上下文的不同,这些问题可能是也可能不是真正的问题。

关于你的第二个无关问题:

void f( int arr[10] );

与完全相同

void f( int* arr );

并且可以为它提供相同的默认参数。

在一维数组的情况下,以下声明是等效的:

void f(int arr[10]);
void f(int* arr);

如果函数确实总是期望一个由10个元素组成的数组,那么第一个声明就是一个好的样式。

但是,请注意,在访问arr[9]以外的元素时,它不会防止运行时错误。

在多维数组的情况下,以下声明是而不是等价的:

void f(int arr[][10]);
void f(int** arr);

第一个实际上告诉编译器如何"索引数组"。

因此,它不仅是一个好的样式,而且对于代码的正确工作也是必不可少的。

这是一种糟糕的风格。首先,它并没有真正检查传递数组的大小(你可以将int[20]甚至int*传递到这个函数中。其次,它可能会导致隐藏的错误,比如:

void f(int arr[10])
{
int other_array[10];
assert(sizeof(arr) == sizeof(other_arr)); // <- actually, the size is different
}

它只是将arr视为一个指针。看看下面的代码:

void f (int arr[10])
{
cout<<sizeof(arr)/sizeof(arr[0]); //prints 1
}

main()
{
int arr[20];
cout<<sizeof(arr)/sizeof(arr[0]); //prints 20
f(arr);
}

对于第二部分,是的。如果没有传递任何参数,则指向int(即arr)的指针将为NULL

以下内容:

void f (int arr[10]);

似乎声明了一个函数,该函数按值接受10个ints的数组,但它只是:

void f (int *arr);

也就是说,它是一个无声的杀手,可能很容易导致未定义的行为,就像下面的例子一样,试图访问超出阵列边界的内存:

#include <iostream>
void f (int arr[10]) {
arr[4] = 7;
}
int main() {
int a[2] = {1,2};
f(a);
}

通过指针或引用获取C样式数组可能更简单:

void f (int (&arr)[10]);
void f (int (*arr)[10]);

而且由于编译器会抱怨(关于前面的例子),所以不太容易出错:

类型为"int(&)[10]'的表达式中类型为"int(amp;)[10]"的引用的初始化无效

或在尝试用&a:初始化指针的情况下

无法将参数"1"的"int()[2]"转换为"int()[10]"到"void f(int(*)[10])">


但我在这里看到的最合理的解决方案是避免完全使用C样式数组,而使用STL容器。如果大小是固定的,并且您支持C++11,则可以考虑使用std::array<int, 10>,否则使用std::vector:

#include <iostream>
#include <vector>
void f (std::vector<int> &vec) {
vec[4] = 7;
}
int main() {
std::vector<int> vec(10,0);
f(vec);
std::cout << vec[4];
}