关于函数strcpy和strncpy的细节

参考:
别再耍流氓了: 请别再用strcpy, 而用strncpy_认知 行动 坚持-CSDN博客
C/C++笔记–strcpy和strncpy函数的安全性分析_xpu_zhouxin的博客-CSDN博客

strcpy有什么危险?

函数原型:

char* strcpy(char* strDest, const char* strSrc)
char* strncpy(char* strDest, const char* strSrc, size_t n)

strcpy: 用于拷贝字符串,会拷贝 '\0',当源串出现 '\0' 时拷贝才结束。如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出的错误,可能造成程序崩溃。

int main(){
    char str[4] = {0};
    char *p = "123456";
    strcpy(str, p);
    cout << str << endl;
    return 0;
}

关于函数strcpy和strncpy的细节_第1张图片

strncpy:用于拷贝字符,并不保证 '\0'结束,不一定会拷贝 '\0'。用来复制源字符串的前n个字符,src 和 dest 所指的内存区域不能重叠,且 dest 必须有足够的空间放置n个字符

可以这么使用:

int main(){
    char str[4] = {0};
    char *p = "1234567890";
    cout << sizeof(str) << endl;
    strncpy(str, p, sizeof(str));
    cout << str << endl;
    return 0;
}

那其实也看到了strncpy也是有很多限制的,比如src 和 dest 所指的内存区域不能重叠,且 dest 必须有足够的空间放置n个字符。所以一旦不小心忽视这些限制,也可能出错。并且,该函数只是拷贝相应的字符,并不会在意\0怎么样怎么样:

如果目标长>指定长>源长,则将源长全部拷贝到目标长,自动加上\0
如果指定长<源长,则将源长中按指定长度拷贝到目标字符串,不包括\0
如果指定长>目标长,运行时错误

上面三条并没有测试,来自开头的参考链接。

所以更好的方式其实是使用:memcpy函数,该函数拷贝是按字节拷贝的,可以拷贝任意类型的数据,而strcpy只能用来拷贝字符串。并且,memcpy函数更为安全。

关于memcpy函数,可以看这个记录的第三个:

9.06腾讯初试记录_zj-CSDN博客

最后如果需要自己实现一个strcpy函数的话,可以一步一步来。

开始可以这么写:

char* my_strcpy(char *dst, const char *src){
    assert((dst != NULL) && (src != NULL));
    char *p = dst;//保存地址,方便返回
    while(*src != '\0'){
        *dst++ = *src++;
    }
    *dst = '\0';//手动加上\0
    return p;
}

说一下几个需要注意的点:

  • 返回目的地址是为了方便链式操作
  • 源地址的参数带const为了防止修改
  • 开头的assert进行参数合法性检查

更为优雅的函数原型:

char* my_strcpy(char *dst, const char *src){
    assert((dst != NULL) && (src != NULL));
    char *p = dst;//保存地址,方便返回
    while((*dst++ = *src++) != '\0'){
    }   
    return p;
}

这种简单的函数反而有很多容易忽视的地方。

strncpy:

char* my_strncpy(char *dst, const char *src, size_t n){
    assert((dst != NULL) && (src != NULL));
    char *p = dst;//保存地址,方便返回
    while(n){
        if(*src != '\0')   *dst++ = *src++; 
        --n;
    }
    *dst = '\0';//手动加上\0
    return p;
}

同理strlen函数(不考虑\0,而sizeof函数会考虑)也可以比着写:

int my_strlen(const char *str){
    assert(str != NULL);
    int len;
    while(*str++ != '\0'){
        ++len;
    }
    return len;
}

你可能感兴趣的:(面试/笔试,strcpy)