在 C 中,当您将数组传递给函数时,数组“衰减”为指针。该函数接收指向数组第一个元素的指针。它不接收数组本身。在被调用函数中对指针分配所做的任何更改都不会反映在调用函数中。
在您的第一个示例中,test()
接收字符串数组,并在函数内部更改该指针指向的内容。所以 的本地副本ptr
,也就是NULL
,在函数内部获得分配的内存,就像ptr[0]
. 但是,这些更改是本地的test()
。它们不会反映在调用函数中。当test()
执行完毕并返回时,ptr
调用函数中的值仍然是NULL
。而且您有内存泄漏,因为无法访问在test()
.
为了使更改反映在调用函数中,您必须传递一个指向字符串数组的指针:因此&ptr
调用中的 和定义中的三级指针test()
。另一种更简单的方法是:
int main()
{
char **ptr= NULL;
ptr = test();
printf("%s", ptr[0]);
return 0;
}
char** test(void)
{
char **ptr = (char **) malloc(sizeof(char *));
ptr[0] = (char *) malloc(sizeof(char) * 5);
strcpy(ptr[0], "abc");
return ptr;
}
一个澄清:我说“对被调用函数中的指针分配所做的任何更改都不会反映在调用函数中。” 这与说“对数组元素的任何更改都不会反映在调用函数中”不同。考虑一下:
int main (void) {
int array [] = { 0, 1, 2, 3, 4 };
test1 (array);
printf ("%d\n", *array);
test2 (array);
printf ("%d\n", *array);
return 0;
}
void test1 (int* array) {
int new_array[] = { 3, 4, 5, 6, 7 };
array = new_array;
return;
}
void test2 (int* array) {
array [0] = 5; // or *array = 5
array [1] = 6;
array [2] = 7;
array [3] = 8;
array [4] = 9;
return;
}
输出:
0
5
这里test1()
的变化是数组指针本身指向的位置,这不会反映在调用者中。所以在调用函数中,*test
依然是0。在test2()
中,变化的是数组元素,反映在调用者中。因此输出的差异:*test
现在是 5。所有这些都使用静态而不是动态内存分配,但原理是相同的。