如果我想将已知或未知大小的数组作为函数参数传递,我对使用哪种语法感到困惑。
假设我有这些变体的目的:
void func1(char* str) {
//print str
}
void func2(char str[]) {
//print str
}
void func3(char str[10]) {
//print str
}
使用其中每一种的优缺点是什么?
所有这些变体都是相同的。C 只允许您使用替代拼写,但即使是最后一个用数组大小显式注释的变体也会衰减为普通指针。
也就是说,即使使用最后一个实现,您也可以使用任意大小的数组调用函数:
void func3(char str[10]) { }
func("test"); // Works.
func("let's try something longer"); // Not a single f*ck given.
不用说不应该使用它:它可能会给用户一种错误的安全感(“哦,这个函数只接受长度为 10 的数组,所以我不需要自己检查长度”)。
正如 Henrik 所说,C++中的正确方法是使用std::string
,std::string&
或std::string const&
(取决于您是否需要修改对象,以及是否要复制)。
请注意,在 C++ 中,如果数组的长度在编译时已知(例如,如果您传递了一个字符串文字),您实际上可以获得它的大小:
template<unsigned int N>
void func(const char(&str)[N])
{
// Whatever...
}
int main()
{
func("test"); // Works, N is 5
}
这些在功能上都是相同的。当您将数组传递给 C 中的函数时,数组会隐式转换为指向数组第一个元素的指针。因此,这三个函数将打印相同的输出(即指向 的指针的大小char
)。
void func1(char* str) {
printf("sizeof str: %zu\n", sizeof str);
}
void func2(char str[]) {
printf("sizeof str: %zu\n", sizeof str);
}
void func3(char str[10]) {
printf("sizeof str: %zu\n", sizeof str);
}
此转换仅适用于数组的第一维。Achar[42][13]
转换为 a char (*)[13]
,而不是a char **
。
void func4(char (*str_array)[13]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
char (*)[13]
是 的类型str_array
。char
这就是您编写“指向 13 s数组的指针”的方式。这也可以写成void func4(char str_array[42][13]) { ... }
,尽管 42 在功能上没有意义,正如您通过实验看到的那样,将不同大小的数组传递到func4
.
在 C99 和 C11(但不是 C89 或 C++)中,您可以将指向可变大小数组的指针传递给函数,方法是将其大小连同它一起传递,并将大小标识符包含在[square brackets]
. 例如:
void func5(size_t size, char (*str_array)[size]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
这声明了一个指向大小 char
为s的数组的指针。请注意,您必须先取消引用指针,然后才能访问数组。在上面的示例中,sizeof str_array[0]
计算数组的大小,而不是第一个元素的大小。例如,要访问第 11 个元素,请使用(*str_array)[11]
or str_array[0][11]
。
在 C++ 中,使用void func4(const std::string& str)
.
在 C 中,前两个定义是等价的。第三个基本相同,但它给出了关于数组大小的概念。
如果打印str
是您的意图,那么您可以安全地使用它们中的任何一个。基本上所有三个函数都传递了一个类型的参数char*
,正是printf()
需要打印一个字符串的参数。以免你不知道,尽管看起来,在 C 中传递的所有参数都是在pass-by-value
模式下完成的。
编辑:似乎我以后在选择 SO 时必须非常严格。好吧,在第三种情况下,它不知道数组的大小给它传递给的函数,因为它最终会减少就像在前两种情况下一样输入char*
。我的意思是说它有点告诉阅读它的人数组的大小是 10。此外,它在 C 中并没有错/非法。但是对于程序来说,这样做就像没用。它对传递给它的函数的数组大小一无所知。Downvoter 先生,感谢您指出 SO 不容忍随意的态度和疏忽。
在一个一维数组中,编译器对它们的处理都是一样的。然而,对于二维或多维数组(例如myArray[10][10]
),它很有用,因为它可用于确定数组的行/列长度。
附加组件,以点为单位进行描述。
1)正如大家所说的一样。
2) 数组在函数参数中传递时会衰减为指针。
3)基本问题可能是在函数中找到数组的大小。为此,我们可以使用类似宏。
#define noOfElements(v) sizeof(v)/sizeof(0[v])
int arr[100]
myfunction ( arr, noOfElements(arr))
宏中可以使用 0[v] 或 v[0],其中第一个用于避免将用户定义的数据类型传递给 noOfElements。
希望这可以帮助。