当前位置:   article > 正文

C字符串拷贝和拼接如何避免内存重叠_c sttrcpy() 内存重叠

c sttrcpy() 内存重叠

C字符串拷贝和拼接如何避免内存重叠

在 C 语言中,字符串拷贝可以使用 strcpy() 函数,使用 strcat() 函数可以实现字符串拼接。但是,使用 strcpy()strcat() 有可能存在内存重叠问题,导致拷贝和拼接之后的结果不正确。为了避免这种问题,有两种做法:

使用 memmove() 函数代替

memmove() 函数能够处理内存重叠的情况,因为它可以在拷贝之前检查传递给它的两个内存区域是否重叠,并且选择了相应的拷贝方式。如果它们重叠,它会将字符从前往后拷贝,从而避免了数据丢失或混乱。

以下是一个示例,演示了如何使用 memmove() 函数实现字符串拷贝:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 50

int main() {
    char src[] = "Hello, world";
    char dest[MAX_LEN];

    int len = strlen(src);

    /* 检测内存重叠并拷贝字符串 */
    if (memmove(dest, src, len) == NULL) {
        printf("Error occurred while copying memory\n");
        return 1;
    }

    printf("%s\n", dest);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在上面的代码中,首先定义了一个字符数组 src,用于存储源字符串。然后定义一个空数组 dest,用于存储拷贝后的字符串。在拷贝字符串之前,获取了源字符串的长度。在进行字符串拷贝之前,使用 memmove() 函数将源字符数组的内容拷贝到目标字符数组,从而实现字符串拷贝。

需要注意的是,memmove() 函数比 strcpy() 函数更加安全,但它也比 strcpy() 函数更加费时。因此,在实际使用中,我们应该权衡使用哪个函数。如果需要精确控制字符串的拷贝,建议使用 memmove() 函数。

以下是一个示例,演示了如何使用 memmove() 函数实现字符串拼接:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 50

int main() {
    char str1[MAX_LEN] = "Hello, ";
    char str2[] = "world!";

    int len1 = strlen(str1);
    int len2 = strlen(str2);

    /* 检测内存重叠并拼接字符串 */
    if (len2 >= (MAX_LEN - len1)) {
        printf("Can not concatenate: Maximum length exceeded\n");
        return 1;
    }

    if (memmove(str1 + len1, str2, len2) == NULL) {
        printf("Error occurred while copying memory\n");
        return 1;
    }

    printf("%s\n", str1);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在上面的代码中,首先定义了两个数组 str1str2str1 数组用于存储第一个字符串,str2 数组用于存储第二个字符串。然后分别获取 str1str2 的长度。在进行字符串拼接之前,对两个字符串的长度进行了检查,以避免发生内存溢出。最后,使用 memmove() 函数将 str2 拷贝到 str1 的末尾,从而实现了字符串拼接。

值得注意的是,memmove() 函数比 strcat() 函数更加安全,但它也比 strcat() 函数更加费时。因此,我们应该在实际应用中权衡使用哪个函数。如果需要精确控制字符串的拼接,建议使用 memmove() 函数。

自己实现 memmove() 函数

memmove() 函数主要用于拷贝一段内存区域中的数据,包括非重叠和重叠区域,可以实现内存区域之间的复制。以下是一个简单的 memmove() 函数实现:

#include <stdio.h>

/* 将 src 数组中的 n 个字符拷贝到 dest 数组中 */
void* my_memmove(void *dest, const void *src, size_t n) {
    char *p_dest = (char*) dest;  // dest 数组指针
    char *p_src = (char*) src;    // src 数组指针

    /* 判断 src 和 dest 是否重叠,进行相应的拷贝 */
    if (p_dest > p_src && p_dest < p_src + n) {
        for (int i = n - 1; i >= 0; i--) {
            *(p_dest + i) = *(p_src + i);
        }
    } else {
        for (int i = 0; i < n; i++) {
            *(p_dest + i) = *(p_src + i);
        }
    }

    return dest;
}

int main() {
    /* 测试 */
    char src[] = "Hello, world";
    char dest[] = "************";
    printf("%s\n", dest);
    my_memmove(dest, src, 13);
    printf("%s\n", dest);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

my_memmove() 函数定义了两个指针变量,分别指向源数组和目标数组。首先判断源数组和目标数组是否重叠,如果重叠,则从后往前拷贝,否则从前往后拷贝。最后返回目标数组的指针。在测试中,程序将源字符串拷贝到用星号填充的目标字符串中,并打印拷贝结果。

需要注意的是,在实际编程中,建议使用系统提供的 memmove() 函数而不是手动实现。因为系统提供的函数通常经过了优化和测试,并且具有更高的效率和更好的安全性。手动实现可能会引入潜在的错误和安全问题。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/430015
推荐阅读
相关标签
  

闽ICP备14008679号