strcpy & strncpy

2010-09-11 17:50

strcpy与strncpy

从现在开始我们要用到很多库函数,在学习每个库函数时一定要看Man Page。Man Page随时都在我们手边,想查什么只要敲一个命令就行,然而很多初学者就是不喜欢看Man Page,宁可满世界去查书、查资料,也不愿意看Man Page。据我分析原因有三:

  1. 英文不好。那还是先学好了英文再学编程吧,否则即使你把这本书都学透了也一样无法胜任开发工作,因为你没有进一步学习的能力。

  2. Man Page的语言不够友好。Man Page不像本书这样由浅入深地讲解,而是平铺直叙,不过看习惯了就好了,每个Man Page都不长,多看几遍自然可以抓住重点,理清头绪。本节分析一个例子,帮助读者把握Man Page的语言特点。

  3. Man Page通常没有例子。描述一个函数怎么用,一靠接口,二靠文档,而不是靠例子。函数的用法无非是本章所总结的几种模式,只要把本章学透了,你就不需要每个函数都得有个例子教你怎么用了。

总之,Man Page是一定要看的,一开始看不懂硬着头皮也要看,为了鼓励读者看Man Page,本书不会像[K&R]那样把库函数总结成一个附录附在书后面。现在我们来分析strcpy(3)

图 24.1. strcpy(3)

strcpy(3)

这个Man Page描述了两个函数,strcpystrncpy,敲命令man strcpy或者man strncpy都可以看到这个Man Page。这两个函数的作用是把一个字符串拷贝给另一个字符串。SYNOPSIS部分给出了这两个函数的原型,以及要用这些函数需要包含哪些头文件。参数destsrcn都加了下划线,有时候并不想从头到尾阅读整个Man Page,而是想查一下某个参数的含义,通过下划线和参数名就能很快找到你关心的部分。

dest表示Destination,src表示Source,看名字就能猜到是把src所指向的字符串拷贝到dest所指向的内存空间。这一点从两个参数的类型也能看出来,destchar *型的,而srcconst char *型的,说明src所指向的内存空间在函数中只能读不能改写,而dest所指向的内存空间在函数中是要改写的,显然改写的目的是当函数返回后调用者可以读取改写的结果。因此可以猜到strcpy函数是这样用的:

char buf[10];strcpy(buf, "hello");printf(buf);

至于strncpy的参数n是干什么用的,单从函数接口猜不出来,就需要看下面的文档。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

在文档中强调了strcpy在拷贝字符串时会把结尾的'\0'也拷到dest中,因此保证了dest中是以'\0'结尾的字符串。但另外一个要注意的问题是,strcpy只知道src字符串的首地址,不知道长度,它会一直拷贝到'\0'为止,所以dest所指向的内存空间要足够大,否则有可能写越界,例如:

char buf[10];strcpy(buf, "hello world");

如果没有保证src所指向的内存空间以'\0'结尾,也有可能读越界,例如:

char buf[10] = "abcdefghij", str[4] = "hell";strcpy(buf, str);

因为strcpy函数的实现者通过函数接口无法得知src字符串的长度和dest内存空间的大小,所以“确保不会写越界”应该是调用者的责任,调用者提供的dest参数应该指向足够大的内存空间,“确保不会读越界”也是调用者的责任,调用者提供的src参数指向的内存应该确保以'\0'结尾。

此外,文档中还强调了srcdest所指向的内存空间不能有重叠。凡是有指针参数的C标准库函数基本上都有这条要求,每个指针参数所指向的内存空间互不重叠,例如这样调用是不允许的:

char buf[10] = "hello";strcpy(buf, buf+1);

strncpy的参数n指定最多从src中拷贝n个字节到dest中,换句话说,如果拷贝到'\0'就结束,如果拷贝到n个字节还没有碰到'\0',那么也结束,调用者负责提供适当的n值,以确保读写不会越界,比如让n的值等于dest所指向的内存空间的大小:

char buf[10];strncpy(buf, "hello world", sizeof(buf));

然而这意味着什么呢?文档中特别用了Warning指出,这意味着dest有可能不是以'\0'结尾的。例如上面的调用,虽然把"hello world"截断到10个字符拷贝至buf中,但buf不是以'\0'结尾的,如果再printf(buf)就会读越界。如果你需要确保dest'\0'结束,可以这么调用:

char buf[10];strncpy(buf, "hello world", sizeof(buf));buf[sizeof(buf)-1] = '\0';

strncpy还有一个特性,如果src字符串全部拷完了不足n个字节,那么还差多少个字节就补多少个'\0',但是正如上面所述,这并不保证dest一定以'\0'结束,当src字符串的长度大于n时,不但不补多余的'\0',连字符串的结尾'\0'也不拷贝。strcpy(3)的文档已经相当友好了,为了帮助理解,还给出一个strncpy的简单实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值