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函数相关推荐

  1. strncpy()函数用法及其详解

    strcpy()函数用法及其详解 strcpy()和strcat()函数都有相同的问题,他们都不能检验目标空间是否能够容纳源字符串的副本. 所以,拷贝字符串用strncpy()函数更加安全 描述: C ...

  2. 【C语言】strncpy函数和strncpy_s函数的不同!关于末尾追加\0

    今天在微软家的strncpy_s函数上栽了跟头,记录一下 char *strncpy(char *strDest, const char *strSource, size_t count ); err ...

  3. 牛客练习赛81 E. 小 Q 与函数求和 1( “简单莫比乌斯反演” ,欧拉函数性质)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 牛客练习赛81 E. 小 Q 与函数求和 1( "简单莫比乌斯反演" ) Prob ...

  4. Matlab绘制小波尺度函数和小波函数

    %小波尺度函数和小波函数 clear,clc,close all; figure,[phi1,psi1,xval1] = wavefun('haar',8,'plot'); figure,[psi2, ...

  5. 这是我转贴的strcpy函数与strncpy函数的比较,其中有些错误,建议大家还是看msdn,要好的多

    strcpy与strncpy函数 (1) Memset 原型:extern void *memset(void *buffer, int c, int count); 用法:#include 功能:把 ...

  6. strlen函数,strcat函数,strcpy函数,strncpy函数,strcmp函数

    strcpy函数: char *strcpy(char *Dest , const char *Src) { assert((Dest != NULL) && (Src != NULL ...

  7. linux c之strncpy函数和strncmp函数最简单使用总结

    1.原型声明: char * strncpy(char *dest,const char *src, size_t n); strncmp() 用来比较两个字符串的前n个字符,区分大小写,其原型为: ...

  8. 小 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)ϕ ...

  9. java strcpy,详解C语言中strcpy()函数与strncpy()函数的使用

    C语言strcpy()函数:复制字符串 头文件:#include 定义函数: char *strcpy(char *dest, const char *src); 函数说明:strcpy()会将参数s ...

最新文章

  1. 50 xen虚拟化技术基础、xen虚拟化技术进阶
  2. shell date 获取昨天日期
  3. js学习-DOM之动态创建元素的三种方式、插入元素、onkeydown与onkeyup两个事件整理...
  4. 安全行业中的event与incident区别
  5. 剔除异常值栅格计算器_R语言系列 数据清洗3 异常值处理
  6. 前端学习资料(书籍和视频)
  7. Spring Boot教程(7) – 直观地理解Spring容器
  8. 错误:unrecognized command line option “-std=c++11”
  9. 算法之排序算法-直接插入排序
  10. 对于网络爬虫的提问?
  11. 一文读懂python本地开发环境配置
  12. 【正在完善】高级CSS特效解析其示范案例
  13. 【C】少年时代的经典游戏:三子棋
  14. html如何将地址、路径、支付code_url转成二维码
  15. MobaXterm登录密码重置
  16. plotly 坐标轴(axes)设置
  17. 我的第一次知识图谱问答
  18. python定义变量类型为数字_python 学习(四)- 变量类型
  19. 思考模式:六顶思考帽(Six Thinking Hats)
  20. ECharts 修改背景格子线条的颜色

热门文章

  1. 传说中Google AdWords黄金账户的标准
  2. mt6589+android+4.4,MT6589T四核/评测总结_小米 红米_手机Android频道-中关村在线
  3. (附源码)ssm大学生时间管理分析系统设计与实现 毕业设计130930
  4. 入职第一天,出事了!
  5. 清华大学王东:语音识别中的大数据与小数据学习
  6. P2P之UDP穿透NAT的原理与实现(附源代码)(转)
  7. 小米系统通知服务器,小米系统的通知栏和状态栏原来有这么多用法,学到了,实用!...
  8. Casularm 自动灌水机脚本
  9. 期刊资源共享(转自绿盟安全论坛)
  10. 大学毕业生如何正确还国家助学金贷款,避免误操作