strcpy的C实现不会改变变量值

所以,我正在尝试实现我自己的strcpy以更好地理解指针在C中是如何工作的,到目前为止我都处于亏损状态。 我尝试了很多不同的方法,尝试使用网络中的代码,以后可能会使用它,但即便是那些也无法工作。

我相信我可能会在main方法上以错误的方式调用函数。 我将变量的指针传递给函数,以便函数可以更改变量的值,并在函数调用中,我给出指针的地址,以便方法可以获取正确的数据。 至少我相信这是它的工作原理,无论如何我都能理解。

以下是函数和方法调用:

function调用:

void my_strcpy( char *dest, const char* src ) { dest = malloc(sizeof(src)); while ( src != '\0' ) { *dest = *src; src++; dest++; } } 

主要:

 int main () { const char* s = "Hello World"; char* test = 'd'; my_strcpy( &test, &s ); // Suposed to change test form d to Hello World. printf("Changed String: " ); printf( "%c", test ); return 0; } 

PS:我尝试使用test作为比s更大的字符串来查看它是否是内存分配问题,但似乎并非如此。 任何帮助都非常令人沮丧,因为我已经被困在这里好几个小时……

PS:我已经研究了如何更改变量的问题和示例,并且可以使用简单的int来完成。 但是在使用char *时我不能这样做。 因此这个post。 如果问题相同,我道歉,但我无法理解我在这里做错了什么。 请耐心等待我,因为我是C的初学者。

关键点在于参数是用 C中的值传递的

因此,调用函数永远不会看到正式参数的任何变化。

最后,你的my_strcpy表现不像标准的strcpy (它不使用malloc分配内存)。 你使用malloc是错误的,因为sizeof(src)总是sizeof(char*) (即Linux / x86-64上的8)。

这是一个更好的版本:

  void my_strcpy( char *dest, const char* src ) { while ( *src != '\0' ) { *dest = *src; src++; dest++; } *dest = '\0'; // zero terminate the string } 

请注意, strcpy (和my_strcpy )本质上是危险的,因为您可能有缓冲区溢出 (因此更频繁地使用strncpy )。 一个典型的用例是

  char buf[80]; my_strcpy(buf, "hello I am here"); 

所以我们有本地内存(通常在调用堆栈上),我们将其复制到其中。 如果文字字符串很长(例如超过80个字符),我们就会有缓冲区溢出。

顺便说一句,你的测试while(src != '\0')非常错误。 指针与指向的值不同。 您的错误测试通常会在32位计算机上循环十亿次,并在到达终止条件src == NULL之前崩溃

同样在实践中strcpy通常是通过优化编译器(如GCC)来实现的 ,它们甚至可以在编译时生成循环,而不是对标准函数的函数调用。

如果您在编译器中启用所有警告 (您应该总是这样),您的编译器(例如GCC )可能会发现您的一些错误,因此请使用gcc -Wall -Wextra -g编译(以获取所有警告,以及更多警告) ,然后调试信息)然后使用调试器gdb逐步运行程序。

在实践中,如果可能的话,让函数返回指针,比如

  char* my_almost_strdup(const char*src) { size_t ln = strlen(src); char* newptr = malloc(ln+1); if (!newptr) { perror("my_strdup"); exit(EXIT_FAILURE); }; strcpy (newptr, src); return newptr; } 

这有点像标准strdup除了我正在捕获内存不足的错误情况(当malloc失败时)。 通常只显示一些错误消息并退出该失败的情况,但您应该始终处理malloc失败

阅读有关C动态内存管理的更多信息并记录您的内存约定 (当有一个函数通过malloccalloc等分配内存时……你需要记录谁负责释放它以及如何)。

害怕未定义的行为和内存泄漏 。 如果可用,请使用valgrind 。

阅读有关垃圾收集的更多信息(这是一个非常有用的术语和概念)。 您可能希望使用Boehm保守垃圾收集器对某些C程序进行编码(但使用Boehm的GC是一个完整的程序决策)。

在你的main

  my_strcpy( &test, &s ); // VERY BAD 

是多次错误 (因缓冲区溢出而导致未定义的行为)。 您应该传递一个能够包含该字符串的内存区域的地址(包括其终止零字节),并且第二个参数没有正确的类型( &schar**而不是const char* )。

你不需要&来引用char *因为它已经是一个指向一个字符的指针,你不希望char **是指向一个字符的指针。

我打了补丁:

 void my_strcpy(char** dest, const char* src) { const char * srcTemp = src; int i = 1; //+1 for null char while (*srcTemp != '\0') { srcTemp++; i++; } char * destTemp = (char*)malloc(sizeof(char)*i); *dest = destTemp; while (*src != '\0') { *destTemp = *src; src++; *destTemp++; } *destTemp = *src; //copy null char } int _tmain(int argc, _TCHAR* argv[]) { const char* s = "Hello World"; char* test = 0; my_strcpy(&test, s); // Suposed to change test form d to Hello World. printf("Changed String: "); printf("%s", test); return 0; }