70

如果我想将已知或未知大小的数组作为函数参数传递,我对使用哪种语法感到困惑。

假设我有这些变体的目的:

void func1(char* str) {
    //print str
}

void func2(char str[]) {
    //print str
}

void func3(char str[10]) {
    //print str
}

使用其中每一种的优缺点是什么?

4

7 回答 7

87

所有这些变体都是相同的。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&(取决于您是否需要修改对象,以及是否要复制)。

于 2013-04-22T10:16:43.023 回答
24

请注意,在 C++ 中,如果数组的长度在编译时已知(例如,如果您传递了一个字符串文字),您实际上可以获得它的大小:

template<unsigned int N>
void func(const char(&str)[N])
{
    // Whatever...
}

int main()
{
    func("test"); // Works, N is 5
}
于 2013-04-22T13:15:20.907 回答
12

这些在功能上都是相同的。当您将数组传递给 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_arraychar这就是您编写“指向 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]

于 2013-04-22T10:50:56.600 回答
12

在 C++ 中,使用void func4(const std::string& str).

于 2013-04-22T10:13:49.817 回答
2

在 C 中,前两个定义是等价的。第三个基本相同,但它给出了关于数组大小的概念。

如果打印str是您的意图,那么您可以安全地使用它们中的任何一个。基本上所有三个函数都传递了一个类型的参数char*,正是printf()需要打印一个字符串的参数。以免你不知道,尽管看起来,在 C 中传递的所有参数都是在pass-by-value模式下完成的。

编辑:似乎我以后在选择 SO 时必须非常严格。好吧,在第三种情况下,它不知道数组的大小给它传递给的函数,因为它最终会减少就像在前两种情况下一样输入char*。我的意思是说它有点告诉阅读它的人数组的大小是 10。此外,它在 C 中并没有错/非法。但是对于程序来说,这样做就像没用。它对传递给它的函数的数组大小一无所知。Downvoter 先生,感谢您指出 SO 不容忍随意的态度和疏忽。

于 2013-04-22T10:16:54.360 回答
1

在一个一维数组中,编译器对它们的处理都是一样的。然而,对于二维或多维数组(例如myArray[10][10]),它很有用,因为它可用于确定数组的行/列长度。

于 2013-04-22T10:29:18.383 回答
1

附加组件,以点为单位进行描述。

1)正如大家所说的一样。

2) 数组在函数参数中传递时会衰减为指针。

3)基本问题可能是在函数中找到数组的大小。为此,我们可以使用类似宏。

   #define noOfElements(v) sizeof(v)/sizeof(0[v])

   int arr[100]
   myfunction ( arr, noOfElements(arr))

宏中可以使用 0[v] 或 v[0],其中第一个用于避免将用户定义的数据类型传递给 noOfElements。

希望这可以帮助。

于 2013-04-22T11:01:43.713 回答