c语言中的传递数组

c语言中的传递数组,c,arrays,pointers,segmentation-fault,C,Arrays,Pointers,Segmentation Fault,我有一个关于将c中的数组传递给函数的问题 当我运行这个程序时,它会给我一个分段错误 int main() { char **ptr= NULL; test(ptr); printf("%s", ptr[0]); return 0; } void test(char **ptr) { ptr = (char **) malloc(sizeof(char *)); ptr[0] = (char *) malloc(sizeof(char)*5); strcpy(ptr

我有一个关于将c中的数组传递给函数的问题

当我运行这个程序时,它会给我一个分段错误

int main()
{

  char **ptr= NULL;
  test(ptr);
  printf("%s", ptr[0]);
  return 0;
}

void test(char **ptr)
{
  ptr = (char **) malloc(sizeof(char *));
  ptr[0] = (char *) malloc(sizeof(char)*5);
  strcpy(ptr[0], "abc");
  return;

}
但这一切都很好

int main()
{

  char **ptr= NULL;
  test(&ptr);
  printf("%s", ptr[0]);
  return 0;
}

void test(char ***ptr)
{
  *ptr = (char **) malloc(sizeof(char *));
  *ptr[0] = (char *) malloc(sizeof(char)*5);
  strcpy(*ptr[0], "abc");
  return;

}

有人能解释一下原因吗?

这是因为您希望函数不返回值,而是修改已在另一个作用域中创建的变量

您希望从函数中通过
ptr
,最终得到以下结构:

ptr -> b -> []
其中
b
是指向数组
[]
的指针

在第一个示例中,您不是在函数内部修改外部ptr,而是它的副本。在这种情况下,要获得所需的结构,需要函数返回一个char**以便返回分配的指针。你不需要通过最初的ptr

另一方面,在第二个示例中,您将传递一个指向外部ptr的指针,因此该函数将修改外部ptr使用的相同内存空间


我希望这能有所帮助。

这是因为您希望函数不返回值,而是修改您在另一个作用域中已经创建的变量

您希望从函数中通过
ptr
,最终得到以下结构:

ptr -> b -> []
其中
b
是指向数组
[]
的指针

在第一个示例中,您不是在函数内部修改外部ptr,而是它的副本。在这种情况下,要获得所需的结构,需要函数返回一个char**以便返回分配的指针。你不需要通过最初的ptr

另一方面,在第二个示例中,您将传递一个指向外部ptr的指针,因此该函数将修改外部ptr使用的相同内存空间


我希望这能对您有所帮助。

请考虑下面的代码以了解如何处理

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test(char **ptr);

int main()
{
  char *ptr= NULL;
  test(&ptr);
  printf("%s\n", ptr);
  return 0;
}

void test(char **ptr)
{
  *ptr = malloc(sizeof(char *));
  strcpy(*ptr, "abc");
  return;
}
#包括
#包括
#包括
无效试验(字符**ptr);
int main()
{
char*ptr=NULL;
测试(ptr);
printf(“%s\n”,ptr);
返回0;
}
无效测试(字符**ptr)
{
*ptr=malloc(sizeof(char*));
strcpy(*ptr,“abc”);
返回;
}
函数定义中的任何操作都必须反映在主函数中。因此,如果要更改
ptr
变量,必须传递
ptr
变量的地址

ptr
是单指针(
char-ptr
)变量,我们需要传递指针(
&ptr
)变量的地址

在函数定义中,我们接收指针变量的地址,所以参数必须是双指针类型

这个概念类似于通过引用调用

代码中也发生了类似的事情

您需要传递双指针的地址才能更改指针变量


在函数定义中,双指针的地址必须由三指针获取。

请考虑下面的代码以了解如何处理

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test(char **ptr);

int main()
{
  char *ptr= NULL;
  test(&ptr);
  printf("%s\n", ptr);
  return 0;
}

void test(char **ptr)
{
  *ptr = malloc(sizeof(char *));
  strcpy(*ptr, "abc");
  return;
}
#包括
#包括
#包括
无效试验(字符**ptr);
int main()
{
char*ptr=NULL;
测试(ptr);
printf(“%s\n”,ptr);
返回0;
}
无效测试(字符**ptr)
{
*ptr=malloc(sizeof(char*));
strcpy(*ptr,“abc”);
返回;
}
函数定义中的任何操作都必须反映在主函数中。因此,如果要更改
ptr
变量,必须传递
ptr
变量的地址

ptr
是单指针(
char-ptr
)变量,我们需要传递指针(
&ptr
)变量的地址

在函数定义中,我们接收指针变量的地址,所以参数必须是双指针类型

这个概念类似于通过引用调用

代码中也发生了类似的事情

您需要传递双指针的地址才能更改指针变量


双指针的地址必须由函数定义中的三指针获取。

您正在通过值传递参数
ptr
test
中的形式参数
ptr
main
中的实际参数
ptr
是不同的对象,因此更改
test::ptr
的值不会反映在
main::ptr

因此,您需要将指向
ptr
的指针传递到
test
,并且
test
需要取消引用该指针以写入正确的对象

对于任何类型的
T
,如果要修改函数参数的值,需要执行以下操作:

void foo( T *param )
{
  *param = ...;
 }

 void bar( )
 {
   T obj;
   foo( &obj );
 }

在这个特定实例中,
T
char**

您正在通过值传递参数
ptr
test
中的形式参数
ptr
main
中的实际参数
ptr
是不同的对象,因此更改
test::ptr
的值不会反映在
main::ptr

因此,您需要将指向
ptr
的指针传递到
test
,并且
test
需要取消引用该指针以写入正确的对象

对于任何类型的
T
,如果要修改函数参数的值,需要执行以下操作:

void foo( T *param )
{
  *param = ...;
 }

 void bar( )
 {
   T obj;
   foo( &obj );
 }

在这个特定实例中,
T
char**

在C语言中,当您将数组传递给函数时,数组将“衰减”为指针。函数接收指向数组第一个元素的指针。它不接收阵列本身。对被调用函数中的指针赋值所做的任何更改都不会反映在调用函数中

在第一个示例中,
test()
接收字符串数组,并在函数内部更改指针指向的内容。因此
ptr
的本地副本是
NULL
,它在函数中获得分配的内存,就像
ptr[0]
一样。但是,这些更改是本地的
test()
。它们不会反映在调用函数中。Whe
#include <stdio.h>
char *test();
int main()
{
  char *ptr = test();
  printf("%s", ptr);
  free(ptr);
  return 0;
}

char *test()
{
  char *ptr = (char *) malloc(sizeof(char) * 5);
  strncpy(ptr, "abc", 3);
  return ptr;
}