代码之家  ›  专栏  ›  技术社区  ›  User314159

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

  •  1
  • User314159  · 技术社区  · 10 年前

    考虑以下实施 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 ,我指的是指针 目标 在指针所在的相同内存地址 来源 被指向。

    现在当我 printf 目标 ,还应打印 "Source String" 。但事实并非如此。

    有人能解释为什么吗?

    2 回复  |  直到 10 年前
        1
  •  9
  •   user2371524 user2371524    10 年前
    void my_strcpy(char target[], char source[])
    {
       target = source;
    }
    

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

    要实际修改函数中的指针,必须传递 指向此指针的指针 例如:

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

    请注意,这仍然不适用于您的程序,因为在 main() 声明一个数组。无法更改声明数组的地址。这是因为数组 与指针相同(在编写糟糕的C教程中经常可以看到),但当您将其传递给函数时,它只是隐式转换为指向其第一个元素的指针。所以,写作 char *target 在您的 main() 工作,调用函数 my_strcpy(&target, source); .

    还要注意,这是在 不可能 一个副本,因此函数的命名在语义上是错误的。实际复制函数如下所示:

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

    复制单个字符,直到 \0 字符(则表达式的计算结果为 0 而while循环将停止)。这种超级简单的实现为 目标 并确保 source 实际上 0终止 对调用者来说,但它确实或多或少是标准C库的 strcpy()

    编辑 :我只是稍微改变了一下你的函数签名——第一个改变是口味问题,替换 identifier[] 通过 *identifier 我喜欢这样做,因为这是内部发生的事情,所以它更清楚地说明了函数实际需要什么。第二个是添加 const 在适当的情况下:您的函数永远不会改变 来源 ,所以您应该将其显式化--这样编译器可以为您捕获更多错误。

        2
  •  5
  •   user2864740 Heinzi    10 年前

    您需要记住两件事:

    现在

    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 = source;
    

    只需更改位置 目标 指向。现在,两者都指向 目标 来源 指向相同的内存位置,即阵列的地址 来源 在里面 主要的 . 这对 主要的 因为C使用传递值。 函数中的两个指针的地址与数组的地址不同。