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

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

 
  1. errno_t strcpy_s(

  2. char *strDestination,

  3. size_t numberOfElements,

  4. const char *strSource

  5. );

  6.  
  7. Parameters

  8. strDestination

  9. Location of the destination string buffer.

  10. numberOfElements

  11. Size of the destination string buffer in char units for narrow and multi-byte functions, and wchar_t units for wide functions.

  12. strSource

  13. Null-terminated source string buffer.

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

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

 
  1. int _tmain(int argc, _TCHAR* argv[])

  2. {

  3.     char dest[10] = {0};

  4.     char src[] = "12345";

  5.     printf_s("dest string size: %d\n", sizeof(dest));    // 10

  6.     printf_s("src string size: %d\n", strlen(src));        // 6

  7.     //strcpy_s(dest, 5, src);        // 报错:5<strlen(src)

  8.     //strcpy_s(dest, 6, src);        // ok

  9.     strcpy_s(dest, 10, src);    // ok

  10.     //strcpy_s(dest, 11, src);    // 报错:11>sizeof(dest)

  11. getchar();

  12. return 0;

  13. }

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

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

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

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

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

 
  1. int _tmain(int argc, _TCHAR* argv[])

  2. {

  3. char dest[6] = {0};

  4. char src[] = "1234567890";

  5. printf_s("dest string size: %d\n", sizeof(dest)); // 6

  6. printf_s("src string size: %d\n", strlen(src)); // 10

  7. strncpy_s(dest, 6, src, 5); // ok

  8. getchar();

  9. return 0;

  10. }

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

所以,建议大家用 strncpy_s 

猜你喜欢

转载自blog.csdn.net/zxx2096/article/details/81127603
今日推荐