版权声明:本文为博主原创文章,转载时请务必注明本文地址,禁止用于任何商业用途,否则会用法律维权。http ://blog.csdn.net/stpeace/article/details/22581763
************************************************** **************************************
我们先来看看strcpy,下面的程序没有问题:
- #include <iostream>
- 使用命名空间 std;
- int main()
- {
- char str [4] = {0};
- char * p = “abc” ;
- strcpy(str,p);
- cout << str << endl;
- 返回 0;
- }
但是,我运行下面程序的时候,就有问题了:
- #include <iostream>
- 使用命名空间 std;
- int main()
- {
- char str [4] = {0};
- char * p = “abcdefg” ;
- strcpy(str,p);
- cout << str << endl;
- 返回 0;
- }
也许你要说,这是程序猿不小心,str的空间太小,p指向的串太大,程序猿小心注意一下就好了。真的是这样吗?马虎的程序猿还少吗?反正,我有时也是马虎程序猿之一。谁也不敢保证自己在用strcpy的时候,str的空间足够大。你想,系统那么复杂,p指向的串,有时你根本无法预料,对不对?所以,要避免这类程序崩溃,不能仅仅依赖于程序猿的细心和认真,尽管我们可以尽可能细心。
那怎么办?我们看看更安全的strncpy函数吧,原型:char * strncpy(char * dest,char * src,size_t num);
上述有问题的程序应该改为:
- #include <iostream>
- 使用命名空间 std;
- int main()
- {
- char str [4] = {0};
- char * p = “abcdefg” ;
- strncpy(str,p, sizeof (str) - 1);
- cout << str << endl;
- 返回 0;
- }
另外看一下下面这个小程序:
- #include <iostream>
- 使用命名空间 std;
- int main()
- {
- char str [4] = {0};
- char * p = “a \ 0bcdefg” ;
- strncpy(str,p, sizeof (str) - 1);
- cout << str << endl;
- 返回 0;
- }
绝对绝对要注意的是: strncpy并没有拷贝串后的\0字符,而strcpy却拷贝了。这充分说明,strncpy是为拷贝字符而生的,而strcpy是拷贝字符串而生的。但两者都不能越界拷贝。只要正确使用strncpy, 那就比strcpy安全。
看看这个程序:
- #include <iostream>
- 使用命名空间 std;
- int main()
- {
- char str [4] = “xyz” ;
- str [3] = 'w' ; //故意将最后的\ 0换成瓦特
- char * p = “abc” ;
- strcpy(str,p); //把p指向的串拷贝到STR中去(刚好可以容纳)
- cout << str << endl;
- 返回 0;
- }
再看:
- #include <iostream>
- 使用命名空间 std;
- int main()
- {
- char str [4] = “xyz” ;
- str [3] = 'w' ; //故意将最后的'\ 0'换成'W'
- char * p = “abc” ;
- strncpy(str,p, sizeof (str) - 1); //只拷贝了3个字符,没有拷贝'\ 0'
- cout << str << endl;
- 返回 0;
- }
总结一下:
1. 好的程序猿用strncpy, 先定义并初始化char str[MAX + 1] = {0};, 如果在程序中间需要再往str中拷贝串,一定要用memset清零。 拷贝范式为:strncpy(str, p, sizeof(str) - 1); , 流氓程序猿用strcpy, 当然我经常在写博客时这么干.
2. strncpy拷贝的是字符,不拷贝串,所以最后一个\0没有拷贝,所以,拷贝的时候需要对串进行清零处理,一定要养成好习惯。
3. strncpy拷贝时,可能会导致截断,但程序不会崩溃。
4. 根据上面strncpy的原型,其实strncpy也并不一定拷贝num个字符,有特殊情况,比如:
- #include <iostream>
- 使用命名空间 std;
- int main()
- {
- char str [4] = { 'w' , 'x' , 'y' , 'z' };
- char * p = “a \ 0bcdefg” ;
- strncpy(str,p, sizeof (str) - 1);
- cout << int (str [0])<< endl; // '一个'
- cout << int (str [1])<< endl; //'\ 0'
- cout << int (str [2])<< endl; //'\ 0'//确实要注意这个值,不是'b'
- cout << int (str [3])<< endl; //'z'
- 返回 0;
- }
5(后来补充的)用strncpy的时候,要防止内存重叠。