关于strcpy_s第二个参数(目标缓冲区大小)的测试以及更加安全的替代方案

先来看一下msdn上的函数原型和对其参数的解释

errno_t strcpy_s(  
   char *strDestination,  
   size_t numberOfElements,  
   const char *strSource   
); 

Parameters
strDestination
Location of the destination string buffer.
numberOfElements
Size of the destination string buffer in char units for narrow and multi-byte functions, and wchar_t units for wide functions.
strSource
Null-terminated source string buffer.

msdn上说第二个参数 numberOfElements 是目标缓冲区大小。

那么这个大小到底应该设置为多大?相信很多人都有同样的困惑,下面用代码测试一下几种情况。

int _tmain(int argc, _TCHAR* argv[])
{
    char dest[10] = {0};
    char src[] = "12345";
    printf_s("dest string size: %d\n", sizeof(dest));    // 10
    printf_s("src string size: %d\n", strlen(src));        // 6
    //strcpy_s(dest, 5, src);        // 报错:5sizeof(dest)
    getchar();
    return 0;
}

从测试的情况可能得出结论:

使用 strcpy_s 要满足以下条件:strlen(src) < numberOfElements <= sizeof(dest)

这个条件说明要  strlen(src) < sizeof(dest) ,即目标缓冲区的大小一定要大于源字符串的长度


为什么右边有等号左边没有?因为 src 大多情况下是字符串而不是字符数组,而字符串是包含了结束符 null 的,所以在 strcpy_s 的时候要考虑进去。


其实,还有更加安全的方式:用 strncpy_s

int _tmain(int argc, _TCHAR* argv[])
{
	char dest[6] = {0};
	char src[] = "1234567890";
	printf_s("dest string size: %d\n", sizeof(dest));	// 6
	printf_s("src string size: %d\n", strlen(src));		// 10
	strncpy_s(dest, 6, src, 5);  // ok
	getchar();
	return 0;
}

上述代码中,尽管源字符串长度大于目标缓冲区的大小,也不会报错,但是要设置好 strncpy_s 第二和第四个参数的值。简单的说,把 strncpy_s 的第二个参数设置为目标缓冲区的大小,把第四个参数设置为第二个参数的值减 1 就可以了,当然,也可以设置为其他合理的值,比如msdn上面提到的 _TRUNCATE ,这些在msdn上都有详细的说明,大家可以自己去看一看。


所以,建议大家用 strncpy_s


参考:

strncpy_s, _strncpy_s_l, wcsncpy_s, _wcsncpy_s_l, _mbsncpy_s, _mbsncpy_s_l

strcpy_s, wcscpy_s, _mbscpy_s


版权声明

如需转载请注明来源和作者,谢谢!!

本文链接:https://blog.csdn.net/ShiQW5696/article/details/80676290


你可能感兴趣的:(编程基础)