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

考虑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指向指向target = source指向的相同内存地址。

现在当我printf target ,它也应该打印"Source String" 。 但事实并非如此。

有人可以解释原因吗?

 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);

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

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

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

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

您需要记住两件事:

  • 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指向mainsource数组target的第一个元素的地址,指向main数组source的第一个元素的地址。

所以,

 target = source; 

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