目录
strcpy的简单用法
#include <iostream> using namespace std; int main() { char str[4] = {0}; char *p = "abc"; strcpy(str, p); cout << str << endl; // abc return 0; }
拷贝abc到str数组,能正常输出。
strcpy的数据含 0 或者'\0' 带来的问题
- 拷贝字符含'\0'的情况
#include <stdio.h> int main() { char str[10] = {0}; char *p = "ab\0defg"; strcpy(str, p); printf("%s", str); // ab return 0; }
如上,结果为ab ,并没有被完全拷贝
- 拷贝字符含0的情况, 也是会不被完全拷贝,下面的test的调用很常见,可能传入的字符如果含 '\0'或者 0 ,那么会导致不完全拷贝。
#include <stdio.h> void test1 (void* data) { char recv[10]; char* xx = (char*)data; strcpy(recv, xx); printf("test1 [%s]\n", recv); // test1 [1] } void test2 (void* data) { char recv[10]; char* xx = (char*)data; strcpy(recv, xx); printf("test2 [%s]\n", recv); // test2 [10] } int main() { char str1[10] = {'1','\0',0,'1','0','1','0',0}; test1(str1); char str2[10] = {'1','0',0,'1','0','1','0',0}; test2(str2); return 0; }
strncpy
- strncopy能避免上面因字符带0产生的问题吗?很遗憾的是不会,strncpy的源码也是依据0的结束符来判断是否拷贝完成,只是限定了拷贝的个数,避免越界,比如下面这样,也是有问题的,明明strncpy要求拷贝10个,但因为出现的'\0'让拷贝失败
#include <stdio.h> void test1 (void* data) { char recv[10]; char* xx = (char*)data; strncpy(recv, xx,10); printf("test1 [%s]\n", recv); // test1 [12345] } int main() { char str1[10] = {'1','2','3','4','5','\0','7'}; test1(str1); return 0; }
解决方案memcpy:
上面的方案都有毛病,那解决方案就是memcpy
#include <stdio.h> void test1 (void* data) { char recv[10]; char* xx = (char*)data; memcpy(recv, xx,10); printf("test1 ["); for(int i = 0; i < 10; i ++) printf("%c", recv[i]); //test1 [12345789a] 第6个字符为空 printf("]\n"); } int main() { char str1[10] = {'1','2','3','4','5','\0','7','8','9','a'}; test1(str1); return 0; }
但memcpy会把字符的 0 和\0一起拷贝到buffer里,用%s打印依旧会打不出 789a, 但memcpy会根据个数来定需要拷贝多少字节,不会因为0而不拷贝。
简单小结:
- strcpy会根据结束符来限制拷贝个数,会被结束符影响。
- strncpy会根据传入参数限制拷贝的个数,仍然会被结束符影响。
- memcpy的拷贝仅受传入参数限定的个数影响