如果要将大小已知或未知的数组作为函数参数传递,我会对使用哪种语法感到困惑。
假设我有这些变体:
void func1(char* str) { //print str } void func2(char str[]) { //print str } void func3(char str[10]) { //print str }
使用这些方法的优缺点是什么?
在 C + + 中,使用 void func4(const std::string& str)。
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::string、 std::string&或 std::string const&(取决于你是否需要修改对象,以及你是否想要复制)。
std::string
std::string&
std::string const&
在 C 语言中,前两个定义是等价的。第三个本质上是相同的,但它给出了一个关于数组大小的想法。
如果打印 str是您的意图,那么您可以安全地使用它们中的任何一个。实际上,所有这三个函数都被传递一个类型为 char*的参数,这正是 printf()打印字符串所需要的。以免您不知道,不管看起来怎么样,C 中传递的所有参数都是在 pass-by-value模式下完成的。
str
char*
printf()
pass-by-value
编辑: 看起来今后我必须非常严格地选择关于 SO 的词语。在第三种情况下,它并不知道传递给它的数组 功能的大小,因为最终它被简化为 char*类型,就像前两种情况一样。我的意思是,它告诉读数组的人,数组的大小是10。另外,在 C 中这样做并没有错/非法,但是对于程序来说,这样做几乎毫无用处。它不会给出任何关于传递给它的函数的数组大小的信息。下面的选民,感谢你指出,随意的态度和疏忽是不能容忍的。
在一维数组中,编译器对它们的处理都是相同的。然而,对于两维或更多维数组(例如 myArray[10][10]) ,它是有用的,因为它可以用来确定数组的行/列长度。
myArray[10][10]
这些在功能上都是一样的。当您将数组传递给 C 中的函数时,数组将隐式转换为指向数组第一个元素的指针。因此,这三个函数将打印相同的输出(即指向 char的指针的大小)。
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 **。
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中。
str_array
void func4(char str_array[42][13]) { ... }
func4
在 C99和 C11(但不是 C89或 C + +)中,您可以将一个指向大小不同的数组的指针传递给函数,方法是将其大小一起传递,并在 [square brackets]中包含大小标识符。例如:
[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]。
sizeof str_array[0]
(*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 }