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

C implementention of strcpy does not change variable value

所以,我正在尝试实现我自己的 strcpy 以更好地理解指针在 C 中的工作方式,但到目前为止我还是一头雾水。我尝试了很多不同的方法,尝试过使用来自网络的代码,也许以后会以我的代码为基础,但即使是那些也行不通。

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

函数和方法调用如下:

函数调用:

void my_strcpy( char *dest, const char* src ) {

dest = malloc(sizeof(src));

while ( src != '[=10=]' ) {
  *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中传递by value

因此调用函数永远不会看到形式参数的任何更改。

最后,您的 my_strcpy 与标准 strcpy 的行为不同(它不使用 malloc 分配内存)。而且您对 malloc 的使用是错误的,因为 sizeof(src) 始终是 sizeof(char*)(即 Linux/x86-64 上的 8)。

这是一个更好的版本:

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

请注意 strcpy(和 my_strcpy)本质上是危险的,因为您可能有 buffer overflow(所以更经常使用 strncpy)。一个典型的用例是

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

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

顺便说一句,你的测试 while(src != '[=23=]') 非常错误。指针与指向的值不同。您的错误测试通常会在 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 失败时)。在失败的情况下只显示一些错误消息并退出是很常见的,但是你应该 always handle malloc failure

阅读更多关于 C dynamic memory management 记录您的 内存 约定 (当函数通过 malloccalloc 等...您需要记录谁负责释放它以及如何释放它)。

如果有就怕undefined behavior and of memory leaks. Use valgrind

阅读更多关于 garbage collection (it is a very useful terminology and concept). You might want to code some C programs using Boehm conservative garbage collector 的信息(但使用 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 != '[=10=]') {
        srcTemp++;
        i++;
    }
    char * destTemp = (char*)malloc(sizeof(char)*i);
    *dest = destTemp;

    while (*src != '[=10=]') {
        *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;
}