在C dynamic中复制字符串

时间:2018-02-02 16:42:34

标签: c string malloc


我有两个版本的C代码。第一个可以工作,但第二个不起作用 第二个的输出是分段错误,但我不知道为什么 也许有人可以解释我的错误?我真的很感激。

这有效:

#include <stdio.h>
#include <stdlib.h>

void stringcpy(const char*, char*);

    int main() {

        const char * original = "C is fun.";
        int size = sizeof(original) / sizeof(char*);
        copy = (char*)malloc(sizeof(char) * 11 + 1);

        stringcpy(original, copy);
        printf("%s\n", copy);

        free(copy);

        return 0;
    }

    void stringcpy(const char* original, char* copy) {

        int i;
        for(i = 0; *(original + i) != '\0'; i++) {
            *(copy + i) = *(original + i);
        }
        *(copy + i) = '\0';
    }

这不起作用:

#include <stdio.h>
#include <stdlib.h>

void stringcpy(const char*, char*);

int main() {

    const char * original = "C is fun.";

    char * copy;
    stringcpy(original, copy);
    printf("%s\n", copy);

    free(copy);

    return 0;
}

void stringcpy(const char* original, char* copy) {

    int size = sizeof(original) / sizeof(char*);
    copy = (char*)malloc(sizeof(char) * size + 1);

    int i;
    for(i = 0; *(original + i) != '\0'; i++) {
        *(copy + i) = *(original + i);
    }
    *(copy + i) = '\0';
}

2 个答案:

答案 0 :(得分:3)

int size = sizeof(original) / sizeof(char*);

sizeof应用于此处不是数组的指针。这不会返回它指向的字符串的大小。 strlen是你应该在这里寻找的。将上述行替换为此( size确定的解决方案)

int size = strlen(original); // better to use `size_t`

现在发生了什么 - 字符串文字是一个char数组,它衰变成指向第一个元素的指针,并指定了指针值 - 你应用了sizeof。这里没有数组的痕迹。要获得数组可以容纳的元素数,您必须传递数组本身而不是指针。

另一件事是C是按值传递 - 所以这里保留更改要么将指针传递给指针,要么从函数传递分配的内存地址。

sizeof(char)1所以你不需要明确地写它 - 你可以简单地写

copy = malloc(size + 1);

代码:

stringcpy(original, &copy);

void stringcpy(const char* original, char** copy) {

    int size = strlen(original);
    *copy = malloc(size + 1);

    int i;
    for(i = 0; original[i] != '\0'; i++) {
        (*copy)[i] = original[i];
    }
    (*copy)[i] = '\0';
}

我已经通过将指针变量的地址传递给另一个函数向您展示了问题的解决方案。或者(自己尝试),您可以从函数返回分配的内存块地址,并将其分配给copy。这也可以。

编辑:如果您不允许更改功能签名,那么除非您像以前在案例1中那样向copy提供已分配的内存,否则无法进行更改。 < / p>

实现正确行为的另一个方法是做到这一点

char* stringcpy(const char* original) {

    int size = strlen(original) ;
    char* copy = malloc(size + 1);

    int i;
    for(i = 0; original[i] != '\0'; i++) {
        copy[i] = original[i];
    }
    copy[i]=0;
    return copy;
}

并像这样使用

copy = stringcpy(original);

在这个答案中省略了几点:

  • 始终检查malloc的返回值 - 如果它返回NULL,如果您检查它,则不会取消引用它。

  • 请勿将malloc - char*的返回类型强制转换为void*转换。

  • 使用完毕后释放动态分配的内存。

答案 1 :(得分:0)

您在函数内分配的内存是从堆中分配的。退出该函数时,该内存将返回给系统,以便在您返回时不再分配该内存。