为什么仅分配指针的字符串复制函数不起作用?

Why is a string copy function just assigning the pointer not working?

考虑 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"。但事实并非如此。

有人可以解释为什么吗?

您需要记住两件事:

  • 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指向数组首元素的地址targetmainsource指向数组首元素的地址sourcemain.

所以,

target = source;

只是改变了target指向的位置。现在,targetsource 都指向相同的内存位置,即 main 中数组 source 的地址。 这对 main 中的任何一个数组都没有任何影响,因为 C 使用按值传递。 函数中的两个指针与函数中的指针具有不同的地址数组。

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

正如您所写,您在这里所做的是将指针传递给函数。但是指针本身是通过值传递的,因此该函数具有这些指针的本地副本。一旦函数退出,函数内部的 target 就会停止存在。

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

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

请注意,这仍然不适用于您的程序,因为在 main() 中您声明了一个数组。已声明数组的地址不能更改。这是因为数组与指针 不同 (正如您经常可以在写得不好的 C 教程中读到的那样),只是在传递数组时隐式转换为指向其第一个元素的指针到一个函数。所以,在你的 main() 中写 char *target,这个 工作,调用像 my_strcpy(&target, source);.

这样的函数

另请注意,这 绝不是 的副本,因此函数的命名在语义上是错误的。一个真正的复制函数看起来像这样:

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

复制单个字符直到遇到 [=18=] 字符(然后表达式将计算为 0 并且 while 循环将停止)。这个超级简单的实现留下了为 target 提供足够存储空间并确保 source 实际上是 0-terminated 给调用者的负担,但它确实是或多或少是标准 C 库的 strcpy() 所做的。

edit:我只是稍微更改了您的函数签名——第一个更改是个人喜好问题,将 identifier[] 替换为 *identifier。我喜欢这样做,因为无论如何这都是内部发生的事情,所以它使函数实际采用的内容更加清晰。第二个是在适当的地方添加 const:您的函数永远不会更改 source 指向的内容,因此您应该明确这一点——这样编译器可以为您捕获更多错误。