下面的测试基于VS2019,测试过程中会报错并提示使用诸如strcpy_s建议,只需要屏蔽报错强制编译执行即可——在代码开头加上:
#pragma warning(disable:4996)//4996为提示的错误码
1.strcpy/strncpy
char *strcpy(char *dest, const char *src);
char * strncpy(char *dest, const char *src, size_t n);
- dest 为目标字符串指针,src 为源字符串指针。
- 成功执行后返回目标数组指针 dest。
- strcpy() 把src所指的字符串复制到dest 所指的数组中,返回指向 dest 字符串的起始地址。
- strncpy()会将字符串src前n个字符拷贝到字符串dest。
- srrncpy()不会自动添加’\0’
- 测试1:strcpy 正常使用,空间足够无越界
char dest[20];
char src[12] = "Hello-World";
strcpy(dest, src);
printf("dest:%s", dest);
//输出——dest:Hello-World
- 测试2:strcpy dest空间小于src空间
char dest[10];//小于src空间
char src[12] = "Hello-World";
strcpy(dest, src);
printf("dest:%s\n", dest);
//输出——dest:Hello-World
//引发异常:Run-Time Check Failure #2 - Stack around the variable 'dest' was corrupted.
//即:运行时检查失败 #2 - 变量“dest”周围的堆栈已损坏。
- 测试3:strncpy 参数n不超过dest的大小
char dest[10];//小于src空间
char src[12] = "Hello-World";
strncpy(dest, src,9);//参数n=9并没有超出空间限制
printf("dest:%s", dest);
//输出——dest:Hello-Wor烫烫烫虥鍨8?s0
目标字符串后面有乱码
原因: print以’\0’标识结尾。而strncpy并不会在拷贝后自动添加’\0’
4. 测试4:手动在dest末尾添加结束符‘\0’
char dest[10];
char src[12] = "Hello-World";
strncpy(dest, src,9);
dest[9] = '\0';
printf("dest:%s", dest);
//输出——dest:Hello-Wor
正常执行
2.sprintf/snprintf
printf 将输出在命令行显示
sprintf/snprintf 将输出赋值给字符串,其余的基本使用方式和printf一致
int sprintf(char *dest, const char *src, ...);
int snprintf(char *dest, size_t n, const char *src, ...);
- dest 为目标字符串指针,src 为源字符串指针。
- 返回值为被拷贝的字符串的长度,即src的长度
- 参数n算上了’\n’,因此实际只拷贝了n-1个字符
- 测试1:sprintf正常使用,空间足够无越界
char dest[20];
char src[12] = "Hello-World";
int ret=sprintf(dest, src);
printf("dest:%s\n ret=%d\n", dest,ret);
//输出——dest:Hello-World
// ret=11
- 测试2:sprintf dest空间小于src空间
char dest[10];//小于src的空间
char src[12] = "Hello-World";
int ret=sprintf(dest, src);
printf("dest:%s\nret=%d\n", dest,ret);
//输出——dest:Hello-World
// ret=11
//同时引发异常:Run-Time Check Failure #2 - Stack around the variable 'dest' was corrupted.
//即:运行时检查失败 #2 - 变量“dest”周围的堆栈已损坏。
- 测试3:snprintf 参数n不超过dest的大小
char dest[10];
char src[12] = "Hello-World";
int ret=snprintf(dest,7,src);
printf("dest:%s\nret=%d\n", dest,ret);
printf("dest length=%d\n", strlen(dest));
//输出——
//dest:Hello-
//ret=11
//dest length=6
可以看出dest的长度 比参数n少1
3.strncpy/snprintf
从上面strcpy/strncpy,sprintf/snprintf两个测试3可以看出strncpy/snprintf的区别如下:
- 返回值:strncpy是返回目标dest指针,snprintf返回的是被拷贝的字符数,即src的字符数(注意这里不是成功拷贝的字符数)
- 参数n:strncpy是实际拷贝的字符数,snprintf实际拷贝了n-1个字符
- snprintf会自动在dest末尾加上’\0’字符,这样在输出的时候不会导致越界;而strncpy要想正常输出,需要手动在末尾添加’\0’字符
- n的传递:使用sizeof(dest)更安全方便。