为什么字符串复制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中的字符串和数组的理解。
这是我的推理: target
和source
实际上只是指向数组的第一个元素的指针,即。 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
指向main
和source
数组target
的第一个元素的地址,指向main
数组source
的第一个元素的地址。
所以,
target = source;
只需更改target
指向的位置即可。 现在, target
和source
指向相同的内存位置,即指向main
中的数组source
地址。 这对main
任何一个数组没有任何影响,因为C使用pass-by-value。 函数中的两个指针都具有与数组不同的地址。