作为函数参数的传递数组、固定大小数组和数组基地址之间的差异

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

假设我有这些变体:

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


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


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

使用这些方法的优缺点是什么?

40506 次浏览

在 C + + 中,使用 void func4(const std::string& 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::stringstd::string&std::string const&(取决于你是否需要修改对象,以及你是否想要复制)。

在 C 语言中,前两个定义是等价的。第三个本质上是相同的,但它给出了一个关于数组大小的想法。

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

编辑: 看起来今后我必须非常严格地选择关于 SO 的词语。在第三种情况下,它并不知道传递给它的数组 功能的大小,因为最终它被简化为 char*类型,就像前两种情况一样。我的意思是,它告诉读数组的人,数组的大小是10。另外,在 C 中这样做并没有错/非法,但是对于程序来说,这样做几乎毫无用处。它不会给出任何关于传递给它的函数的数组大小的信息。下面的选民,感谢你指出,随意的态度和疏忽是不能容忍的。

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

这些在功能上都是一样的。当您将数组传递给 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]没有一个 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的数组的指针”的方法。这也可以写成 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数组的指针。请注意,在访问数组之前必须取消对 指针的引用。在上面的示例中,sizeof str_array[0]计算的是数组的大小,而不是第一个元素的大小。例如,要访问第11个元素,请使用 (*str_array)[11]str_array[0][11]

附加,用点描述。

1)正如每个人所说的那样。

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

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

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


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

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

希望这个能帮上忙。

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

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


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