为什么字符串复制功能只是指定指针不起作用?

时间:2015-09-13 07:40:48

标签: c pointers strcpy

考虑strcpy的实现:

void my_strcpy(char target[], char source[])
{
   target = source;
}

int main(void)
{
   char target[20];
   char source[] = "Source String";

   my_strcpy(target, source);
   printf("Target: %s", target);

   return 0;
}

这不起作用,这让我质疑我对C中的字符串和数组的理解。

以下是我的推理:targetsource实际上只是指向数组的第一个元素的指针,即。 target == &target[0]source == &source[0]。当我设置target = source时,我将指针target指向指针source指向的同一内存地址。

现在当我printf target时,它还应该打印"Source String"。但它没有。

有人可以解释原因吗?

2 个答案:

答案 0 :(得分:8)

void my_strcpy(char target[], char source[])
{
   target = source;
}

在这里,您所做的是将指针传递给函数。但是指针本身是通过值传递的,因此该函数具有这些指针的本地副本。函数内的target会在函数退出时立即停止。

要实际修改函数中的指针,您必须将指针传递给此指针,例如像这样:

void my_strcpy(char *target[], char source[])
{
   *target = source;
}

请注意,这仍然不适用于您的程序,因为在main()中您声明了一个数组。无法更改声明的数组的地址。这是因为一个数组与指针相同(正如你经常在编写不好的C教程中读到的那样)但是当你将它传递给函数时,它只是隐式转换为指向它的第一个元素的指针。因此,在char *target中写main(),此工作,调用函数my_strcpy(&target, source);

另请注意,这是无法副本,因此您的函数命名在语义上是错误的。真正的复制功能如下所示:

void my_strcpy(char *target, const char *source)
{
   while (*target++ = *source++);
}

复制单个字符,直到达到\0字符(然后表达式将评估为0,而while循环将停止)。这种超级简单的实现为target提供了足够的存储空间,并确保source实际上 0终止给调用者,但确实或多或少标准C库的strcpy()做了什么。

编辑:我刚刚更改了您的功能签名 - 第一个更改是品味问题,将identifier[]替换为*identifier。我喜欢这样做,因为无论如何这都是内部发生的事情,所以它使得函数实际需要的更清楚。第二个是在适当的位置添加const:您的函数永远不会更改source所指向的内容,因此您应该明确这样做 - 这样编译器就可以为您捕获更多错误。

答案 1 :(得分:5)

您需要牢记两件事:

  • C使用pass-by-value
  • 您无法更改自动数组的地址。

现在,

my_strcpy(target, source);

相同
my_strcpy(&target[0], &source[0]);

传递两个数组的第一个元素的地址和

void my_strcpy(char target[], char source[])

相同
void my_strcpy(char* target, char* source)

其中target指向target中数组main的第一个元素的地址,source指向数组的第一个元素source的地址1}} main

所以,

target = source;

只需更改target指向的位置即可。现在,targetsource都指向相同的内存位置,即source中数组main的地址。 这对main中的任何一个数组都没有任何影响,因为C使用pass-by-value。函数中的两个指针都有不同的数组地址。