小探strncpy函数
strncpy函数原型
原型:extern char *strncpy(char *dest, char *src, int n);用法:#include <string.h>功能:把src所指由NULL结束的字符串的前n个字节复制到dest所指的数组中。说明:如果src的前n个字节不含NULL字符,则结果不会以NULL字符结束。如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。如果n<src的长度,只是将src的前n个字符复制到dest的前n个字符,不自动添加'\0',也就是结果dest不包括'\0',需要再手动添加一个'\0'。src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针
注:strlen计算字符串的长度,不算 \0; sizeof是操作符,计算分配的字节大小,算 \0。
内存重叠
内存重叠问题是指目的地址的内存空间的首地址,包含在源内存空间中,这两段内存空间有了交集,因而在使用memcpy进行内存复制操作时,这段重叠的内存空间会被破坏.这种情况在应用程序级代码中一般不会出现的,而在驱动或内核级代码中要十分小心,尽量使用memmove函数。
memcpy对内存空间有要求的,dest和src所指向的内存空间不能重叠,否则复制的数据是错误的.下面具体讲解一下这个错误是如何产生的。如果内存空间布局入下图所示:
src所指向的内存空间后面部分数据被新拷贝的数据给覆盖了(也就是dest<=src+size).所以拷贝到最后,原来的数据肯定不是原来的数据,拷贝的数据也不是想要的数据。下面举例:
int main()
{char message[] = "abcdef";strncpy(message+2 ,message, 3); printf("%s\n",message); //ababafmemcpy(message+2 ,message, 3);printf("%s\n",message); //ababcfreturn 0;
}
结果:srtncpy不支持内存区域重叠;而现在的memcpy已经支持,能够达到和memmove一样的效果,即使在目的地址和原地址存在重叠时也能达到我们想要的结果。
考虑内存重叠
面试中经常会遇到让你写一个能够处理内存重叠的strncpy,标准库中的strncpy是不考虑内存重叠的,如果出现内存重叠,结果将是未定义的。
网上的很多博客也有这个代码的实现,其实很多也是有问题的,没有考虑src长度小于len的问题:
char *strncpy(char *dst, const char *src, size_t len)
{ assert(dst != NULL && src != NULL); char *res = dst; if (dst >= src && dst <= src + len - 1)//重叠,从后向前复制 { dst = dst + len - 1; src = src + len - 1; while (len--) *dst-- = *src--; } else { while (len--) *dst++ = *src++; } return res;
}
那么,如果要处理内存重叠,该怎么办?如果内存重叠和src的长度小于len这两种情况同时出现,又如何处理?
见图,假设红色部分为src,黄色为dst。如果出现内存重叠,我们很容易想到:从后往前拷贝。如果src的长度小于len,则在后面补NUL。
char *strncpy(char *dst, const char *src, size_t len)
{ assert(dst != NULL && src != NULL); char *res = dst; int offset = 0; char *tmp; if (strlen(src) < len)//src长度小于len { offset = len - strlen(src); len = strlen(src); } if (dst >= src && dst <= src + len - 1)//重叠,从后向前复制 { dst = dst + len - 1; src = src + len - 1; tmp = dst; while (len--) *dst-- = *src--; } else { while (len--) *dst++ = *src++; tmp = dst; } while (offset--) { *tmp++ = '\0'; } return res;
}
最后,注意:如果len的值大于dst的值,就会破坏dst后面的内存空间,这应该是要避免的。
如果n =destin串长度,则destin串没有NULL字符,会导致输出会有乱码。如果不考虑source串复制完整性,可以将destin 最后一字符置为’\0’。
参考:深入理解strncpy这个函数
memcpy使用时需要注意的地方
常见字符串函数
C语言之memcpy函数
小探strncpy函数相关推荐
- strncpy()函数用法及其详解
strcpy()函数用法及其详解 strcpy()和strcat()函数都有相同的问题,他们都不能检验目标空间是否能够容纳源字符串的副本. 所以,拷贝字符串用strncpy()函数更加安全 描述: C ...
- 【C语言】strncpy函数和strncpy_s函数的不同!关于末尾追加\0
今天在微软家的strncpy_s函数上栽了跟头,记录一下 char *strncpy(char *strDest, const char *strSource, size_t count ); err ...
- 牛客练习赛81 E. 小 Q 与函数求和 1( “简单莫比乌斯反演” ,欧拉函数性质)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 牛客练习赛81 E. 小 Q 与函数求和 1( "简单莫比乌斯反演" ) Prob ...
- Matlab绘制小波尺度函数和小波函数
%小波尺度函数和小波函数 clear,clc,close all; figure,[phi1,psi1,xval1] = wavefun('haar',8,'plot'); figure,[psi2, ...
- 这是我转贴的strcpy函数与strncpy函数的比较,其中有些错误,建议大家还是看msdn,要好的多
strcpy与strncpy函数 (1) Memset 原型:extern void *memset(void *buffer, int c, int count); 用法:#include 功能:把 ...
- strlen函数,strcat函数,strcpy函数,strncpy函数,strcmp函数
strcpy函数: char *strcpy(char *Dest , const char *Src) { assert((Dest != NULL) && (Src != NULL ...
- linux c之strncpy函数和strncmp函数最简单使用总结
1.原型声明: char * strncpy(char *dest,const char *src, size_t n); strncmp() 用来比较两个字符串的前n个字符,区分大小写,其原型为: ...
- 小 Q 与函数求和 1(牛客练习赛 81 E)
小 Q 与函数求和 1 ∑i=1n∑j=1nϕ(ijgcd(i,j)K)∑i=1n∑j=1ngcd(i,j)Kϕ(ij)∑i=1n∑j=1ngcd(i,j)Kϕ(i)ϕ(j)gcd(i,j)ϕ ...
- java strcpy,详解C语言中strcpy()函数与strncpy()函数的使用
C语言strcpy()函数:复制字符串 头文件:#include 定义函数: char *strcpy(char *dest, const char *src); 函数说明:strcpy()会将参数s ...
最新文章
- 50 xen虚拟化技术基础、xen虚拟化技术进阶
- shell date 获取昨天日期
- js学习-DOM之动态创建元素的三种方式、插入元素、onkeydown与onkeyup两个事件整理...
- 安全行业中的event与incident区别
- 剔除异常值栅格计算器_R语言系列 数据清洗3 异常值处理
- 前端学习资料(书籍和视频)
- Spring Boot教程(7) – 直观地理解Spring容器
- 错误:unrecognized command line option “-std=c++11”
- 算法之排序算法-直接插入排序
- 对于网络爬虫的提问?
- 一文读懂python本地开发环境配置
- 【正在完善】高级CSS特效解析其示范案例
- 【C】少年时代的经典游戏:三子棋
- html如何将地址、路径、支付code_url转成二维码
- MobaXterm登录密码重置
- plotly 坐标轴(axes)设置
- 我的第一次知识图谱问答
- python定义变量类型为数字_python 学习(四)- 变量类型
- 思考模式:六顶思考帽(Six Thinking Hats)
- ECharts 修改背景格子线条的颜色
热门文章
- 传说中Google AdWords黄金账户的标准
- mt6589+android+4.4,MT6589T四核/评测总结_小米 红米_手机Android频道-中关村在线
- (附源码)ssm大学生时间管理分析系统设计与实现 毕业设计130930
- 入职第一天,出事了!
- 清华大学王东:语音识别中的大数据与小数据学习
- P2P之UDP穿透NAT的原理与实现(附源代码)(转)
- 小米系统通知服务器,小米系统的通知栏和状态栏原来有这么多用法,学到了,实用!...
- Casularm 自动灌水机脚本
- 期刊资源共享(转自绿盟安全论坛)
- 大学毕业生如何正确还国家助学金贷款,避免误操作