【C语言】字符串拷贝函数分析

本文详细介绍了C语言中的strcpy、strncpy、strlcpy和memcpy四个字符串复制函数,强调了strcpy可能导致缓冲区溢出的问题,推荐使用strncpy和strlcpy以提高安全性,以及指出memcpy的通用性和用途

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

strcpy函数

        strcpy是一种C语言的标准库函数,strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*(字符型指针)。

原型声明:

char *strcpy(char* dest, const char *src);

        说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。

函数实现:

char *my_strcpy(char *dest, char *src)
{
    char *dest_o = dest;
    while (*src != '\0')
    {
        *dest++ = *src++;
    }
    *dest = '\0';
​
    return dest_o;
}

举例:

#include <stdio.h>
#include <string.h>
​
int main()
{
    char arr[6];
    //arr="abcde"; 有错误
    
    strcpy(arr,"abcde");
    puts(arr); // 输出abcde
​
    return 0;

        缺陷:strcpy函数并不检查目的缓冲区的大小边界,而是将源字符串逐一的全部赋值给目的字符串地址起始的一块连续的内存空间,同时加上字符串终止符。

        处理办法:在编写 strcpy 函数时,首先尽量使目的缓冲区长度足够长,另外要检测目的缓冲区和源缓冲区。如果目的缓冲区或源缓冲区是空,就要在异常处理中结束程序。如果,源字符串比目的缓冲区长度不长,也要在异常处理中结束程序,以防止出现溢出情况。任何程序都很难说是绝对安全,只能以尽可能安全的方式来处理 strcpy 函数。重要的是,即使设计程序时非常仔细,也有可能会忽略一些细节问题,导致不可弥补的错误。所以,在编写程序时,最安全的方法,就是尽可能不去使用 strcpy 函数。

strncpy函数

        strncpy函数用于将指定长度的字符串复制到字符数组中,表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被复制后的dest。

原型声明:

char *strncpy(char *dest, char *src, int n);

        说明:复制字符串 src 中的内容到字符串 dest 中,复制多少由 n 的值决定。如果 src 的前 n 个字符不含 NULL 字符,则结果不会以NULL 字符结束。如果 n <= src 的长度,只是将 src 的前 n 个字符复制到 dest 的前 n 个字符,不自动添加 '\0',也就是结果 dest 不包括 '\0'。如果 n > src 的长度,则以 NULL 填充 dest 直到复制完 n 个字节。src 和 dest 所指内存区域不可以重叠且 dest 必须有足够的空间来容纳 src 的字符长度 + '\0'。

函数实现:

char *my_strncpy(char *dest, const char *src, size_t n)
{
    size_t i;
​
    for (i = 0; i < n && src[i] != '\0'; i++)
        dest[i] = src[i];
​
    for ( ; i < n; i++)
        dest[i] = '\0';
​
    return dest;
}

举例:

#include <stdio.h>
#include <string.h>
​
int main()
{
    char arr[8];
​
    strncpy(arr, "abcdefghijk", 5);
    puts(arr); // 输出abcde
​
    strncpy(arr, "abcdefghijk", 6);
    puts(arr); // 输出abcdef

strncypy与strcpy的区别:

        strcpy只是复制字符串,但不限制复制的数量,很容易造成缓冲溢出。strncpy要安全一些。strncpy能够选择一段字符输出,strcpy则不能。

strlcpy函数

        strlcpy是更加安全版本的strcpy函数,在已知目的地址空间大小为 size 的情况下,把从 src 地址开始且含有 '\0' 结束符的字符串复制到以 dest 开始的地址空间,并不会造成缓冲区溢出,返回实际拷贝的 src 字符串的大小。

原型声明:

size_t strlcpy(char *dest, const char *src, size_t size)

        说明:保证尾部加 '\0',采用截断方式,strlcpy并不属于 ANSI C,至今也还不是标准。

函数实现:

size_t strlcpy(char *dest, const char *src, size_t siz)
{
   char *d = dest;
    const char s = src;
    size_t n = size;
​
    if (n != 0)
    {
        while (–n != 0)
     {
       if ((*d++ = s++) == ‘\0’)
        break;
        }
    }
    
   if (n == 0)
    {
        if (size != 0)
        {
            d = ‘\0’;   
        }
        while (s++);
    }
​
    return(s - src - 1); 
}

strlcpy与strncpy的区别:

        类似的函数还有strncpy,但是strlcpy常常是更加安全地选择,因为strlcpy在复制之后dest字符串一定会以'\0'字符结尾。

memcpy函数

        memcpy是内存拷贝函数。函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,即从源source中拷贝n个字节到目标destin中。

原型声明:

void *memcpy(void *destin, void *source, unsigned n);

函数实现:

void *my_memcpy(void *dest, void *src, size_t len)
{
    char *dest_c = dest;
    char *src_c = src;
    int i;
​
    for (i = 0; i < len; i++)
    {
        dest_c[i] = src_c[i]; 
    }
    
    return dest;
}

        说明:memcpy() 并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。

memcpy和strcpy主要有以下3方面的区别:

        1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。

        2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。

        3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。由于字符串是以“\0”结尾的,所以对于在数据中包含“\0”的数据只能用memcpy。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值