读书人

这几个strcpy到底有多大的差异

发布时间: 2013-08-01 15:23:18 作者: rapoo

这几个strcpy到底有多大的区别
还是K&R书中的程序:


void strcpy1(char *s,char *t)
{
int i = 0;
while((s[i] = t[i]) != '\0')
i++;
}

void strcpy2(char *s,char *t)
{
while((*s = *t) != '\0')
{
s++;
t++;
}
}

void strcpy3(char* s,char* t)
{
while((*s++ = *t++) != '\0')
;
}

void strcpy4(char *s, char* t)
{
while(*s++ = *t++)
;
}


书中说道:“该函数初看起来不太容易理解,但这种表示方法是很有好处的,我们应该掌握这种方法,C语言程序中经常会采用这种写法。”

我很想知道最后一个写法到底有多大的好处?
还是牛人为了体现自己思维能力的优越性?
[解决办法]
没什么区别.
只不过说,很多人都这么写.让你尽早也能这么写,以便于容易理解别人的代码.
C语言本来就是自由,灵活的.怎么写都可以.
[解决办法]
没有提供拷贝长度的函数都很危险
[解决办法]
等价,说等价不是等同,是它们本质是一样的。只是表达形式不同!

一个可以作为另一个简化或者补充解释!
[解决办法]
K&R书上说的意思肯定是这四个函数越来越好了,其实最后两个函数比较好是在于*s++ = *t++这种语句在某些机器上被优化的可能更大,或者某些机器上直接提供了类似的机器指令。至于最后一个最好估计是看起来更简洁。(C语言刚出来那会儿各种厂商生产的硬件比较多。)
[解决办法]
他们的功能是一样的;至于性能上差不了多少;
对于这种性能相差不大的,最好选择可读性强的写法;
便于后期维护。
[解决办法]
还是用限制长度的接口更安全,比如strncpy, 最近我们领导因为代码中都是strcpy和strcat而把我们训了一顿呢。
[解决办法]
别纠结与这些问题,第四个,和第五个都一样,写的话尽量写第四个,简单明了的。一看就知道拷贝到字符串未
[解决办法]
c库函数设计原则, 程序员都是聪明人, 知道自己在干什么,
你传递的字符串没有在合适的位置 '\0' 结尾,
或者给出的缓冲区大小不够,
那是调用方活该倒霉,
是传递一方的责任,
关这个函数鸟事,
说 strcpy 不安全的真是傻逼,
操.

[解决办法]
引用:
Quote: 引用:

第4个其实很危险。
4个函数 都有一样的危险 不会说第四个就危险 其他的就安全 没这回事


确实是这样子的
[解决办法]

区别不大,最后一种最好懂,并且省了中间变量i,省了与0进行比较,直接将值作为布尔值使用,速度也会快些。

不建议像楼上所说的那样使用strncpy代替strcpy

strncpy是可以防止缓冲溢出,但这是不良的习惯,而且运行效率会低于strcpy,也因为这才没有用strncpy直接代替strcpy,而只是做为strcpy的一个补充。

如果出现缓冲溢出,
1.是处理的字符串出现了异常,属于非法状态下的输入,此时需要进行相应处理,还可能需要直接弹出错误。
2.是缓冲区分配错误,此时需要重新修正缓冲区分配算法。
而依靠strncpy是十分可怕的,因为它会让错误被掩盖了。我们不怕程序崩溃,就怕有错误,程序还依然能运行。得到的结果却不是我们想要的。strncpy是自作主张的进行截断,最后的结果就会变成不可预期。

strcpy过界是可以检测出来的,编译器也可产生警告甚至直接崩溃。但strncpy产生的不可预期结果是很难检测的。如你要找一个“小明女朋友”的信息,结果被截断成“小明”,一切都正常,只不过你永远不知道你得到的信息其实不是小明女朋友的,而是小明的。

所以安全的做法是自己在调用前就做检查,一般需要检查长度是否比缓冲区大,指针是否为空。



[解决办法]
引用:
区别不大,最后一种最好懂,并且省了中间变量i,省了与0进行比较,直接将值作为布尔值使用,速度也会快些。

不建议像楼上所说的那样使用strncpy代替strcpy

strncpy是可以防止缓冲溢出,但这是不良的习惯,而且运行效率会低于strcpy,也因为这才没有用strncpy直接代替strcpy,而只是做为strcpy的一个补充。

如果出现缓冲溢出,
1.是处理的字符串出现了异常,属于非法状态下的输入,此时需要进行相应处理,还可能需要直接弹出错误。
2.是缓冲区分配错误,此时需要重新修正缓冲区分配算法。
而依靠strncpy是十分可怕的,因为它会让错误被掩盖了。我们不怕程序崩溃,就怕有错误,程序还依然能运行。得到的结果却不是我们想要的。strncpy是自作主张的进行截断,最后的结果就会变成不可预期。

strcpy过界是可以检测出来的,编译器也可产生警告甚至直接崩溃。但strncpy产生的不可预期结果是很难检测的。如你要找一个“小明女朋友”的信息,结果被截断成“小明”,一切都正常,只不过你永远不知道你得到的信息其实不是小明女朋友的,而是小明的。

所以安全的做法是自己在调用前就做检查,一般需要检查长度是否比缓冲区大,指针是否为空。

楼上提到 strncpy的只有我了
貌似你是在说我 那么我就得澄清一下了
我说 strncpy 是表达 有比_s后缀的函数 更好一点的选择

至于你说的 不怕崩溃 怕出错了还正常运行
那其实和我在20楼的说法是一致的
[解决办法]
strncpy 实现代码更多一些,把没达到长度的都赋值0.
[解决办法]
引用:
Quote: 引用:

请教下如何驾驭,比如有数组char szData[256] = {0};strcpy(szData,szSrc);szSrc是运行时获取到的数据,如果是个错误的数据,其“长度”很有可能超过256。另“_s 后缀的就算了”能否指点下,是因为运行效率低还是一样不安全?
再说 没发现错误 你这样调用出现崩溃的可能性更大 更容易察觉到代码有BUG
使用所谓的安全函数_s 呵呵 你加长度限制了 代码运行正常安全没奔溃了 你觉得这样更容易查找BUG??

首现运行时获取到的数据有时候难以判断数据是否是错误或者正确的,其次这2种情况你是不是搞反了?下面2段代码

//代码一
char szBuffer[6] = {0};
strcpy(szBuffer,"123456789");

//代码二
char szBuffer[6] = {0};
strcpy_s(szBuffer,sizeof(szBuffer),"123456789");

在VS2005上,第一段代码运行并没有马上崩溃,但栈很有可能已经被破坏了,程序运行一段时间后崩溃掉,而第二段代码立马中断。以上2种情况你觉得哪种更方便调试解决问题?
[解决办法]
引用:
Quote: 引用:



区别不大,最后一种最好懂,并且省了中间变量i,省了与0进行比较,直接将值作为布尔值使用,速度也会快些。

不建议像楼上所说的那样使用strncpy代替strcpy

strncpy是可以防止缓冲溢出,但这是不良的习惯,而且运行效率会低于strcpy,也因为这才没有用strncpy直接代替strcpy,而只是做为strcpy的一个补充。

如果出现缓冲溢出,
1.是处理的字符串出现了异常,属于非法状态下的输入,此时需要进行相应处理,还可能需要直接弹出错误。
2.是缓冲区分配错误,此时需要重新修正缓冲区分配算法。
而依靠strncpy是十分可怕的,因为它会让错误被掩盖了。我们不怕程序崩溃,就怕有错误,程序还依然能运行。得到的结果却不是我们想要的。strncpy是自作主张的进行截断,最后的结果就会变成不可预期。

strcpy过界是可以检测出来的,编译器也可产生警告甚至直接崩溃。但strncpy产生的不可预期结果是很难检测的。如你要找一个“小明女朋友”的信息,结果被截断成“小明”,一切都正常,只不过你永远不知道你得到的信息其实不是小明女朋友的,而是小明的。

所以安全的做法是自己在调用前就做检查,一般需要检查长度是否比缓冲区大,指针是否为空。


楼上提到 strncpy的只有我了
貌似你是在说我 那么我就得澄清一下了
我说 strncpy 是表达 有比_s后缀的函数 更好一点的选择

至于你说的 不怕崩溃 怕出错了还正常运行
那其实和我在20楼的说法是一致的


你误会了,我是看了10楼说他们领导的,感叹现在有的领导很偏执。
检测数据完整性和合法性是最基本的,尽早将错误暴露出来,而不是使用具有极大容错性的函数。
容错是必须的,但不是对程序员容错,而是程序员在程序中对用户输入的数据进行容错。

[解决办法]
呵呵,那些说strcpy不安全的,可知Linux内核中一大把一大把的strcpy,有时候效率和安全是不可兼得的,为了追求效率,只好自己去控制安全了。

读书人网 >C语言

热点推荐