传递数组,固定大小的数组和数组的基地址之间的区别作为函数参数

时间:2013-04-22 10:11:58

标签: c++ arrays pointers

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

假设我有这些变体用于此目的:

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

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

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

使用其中每一种的利弊是什么?

7 个答案:

答案 0 :(得分:69)

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

答案 1 :(得分:20)

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

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

int main()
{
    func("test"); // Works, N is 5
}

答案 2 :(得分:11)

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

答案 3 :(得分:8)

这些功能完全相同。将数组传递给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);
}

此转换仅适用于数组的第一个维度。 char[42][13]转换为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的类型。这是你写“指向13 char 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]);
}

这声明了一个指向 size char数组的指针。请注意,您必须取消引用指针才能访问该阵列。在上面的示例中,sizeof str_array[0]计算数组的大小,而不是第一个元素的大小。例如,要访问第11个元素,请使用(*str_array)[11]str_array[0][11]

答案 4 :(得分:1)

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

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

编辑:似乎我必须非常严格地选择在今后的字上。好吧,在第三种情况下,它不知道数组的大小对于传递给它的函数,最终它被缩减为类型char*,就像前两种情况一样。我想说它有点告诉人们读它的数组的大小是10。此外,它在C.But中没有错误/非法。对于程序来说,这样做就像无用一样。它不会对传递给它的函数的数组大小一无所知.Mr.Downvoter,感谢指出SO不容忍随意的态度和疏忽。

答案 5 :(得分:1)

在一维数组中,编译器对它们的处理方式相同。但是对于两维或更多维数组(例如myArray[10][10]),它很有用,因为它可用于确定数组的行/列长度。

答案 6 :(得分:1)

添加点,用点描述。

1)众所周知,它是一样的。

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

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

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

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

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

希望这会有所帮助。