最近遇到字符串导致的乱码问题 特此记录一下:
strcpy_s:
#define _ _STDC_WANT_LIB_EXT1_ _1
#include <string.h>
errno_t strcpy_s(char * restrict s1, rsize_t s1max, const char * restrict s2);
Neithers1nors2shall be a null pointer. s1maxshall not be greater than RSIZE_MAX.
s1maxshall not equal zero. s1max shall be greater thanstrnlen_s(s2, s1max).
Copying shall not take place between objects that overlap.
s1和s2不为空 s1max不超过RSIZE_MAX且不能为0 s1max要比s2的个数大
msdn上有这么一句:
The strcpy_s function copies the contents in the address of strSource, including the terminating null character,
to the location specified by strDestination. The destination string must be large enough to hold the source string,
including the terminating null character. The behavior of strcpy_s is undefined if the source and destination strings overlap.
一句话就是s1max是s2带上空终止符 而s1max一定要比s1的大小小 不然怎么放下
string str_1 = "1234567890987654321";
char str_2[20] = {0};
strcpy_s(str_2, 18, str_1.c_str());
测试发现 strcpy_s的原理应该是:
1:比较s1max和strlen(s2)+1 至少保证s1max大于等于后者
2:复制数据到s1 不管s1的大小是否大于s1max 如果s1小于s1max 肯定是写过界
优点:s1max有效地限制了s2的大小 如果s2+1大于s1max 就直接报错了
缺点:s1max无法限制s1 如果s1比s1max小 可能出现越界写 这个后果更严重
使用场景: strcpy_s(d, _countof(d), s); 务必保证s里的长度加上null 要小于等于d的长度
其中s分为null结尾和非null结尾:非null结尾的加null后和s1max比较 带null的直接比较
扩展:
template <size_t size>
errno_t strcpy_s(
char (&strDestination)[size],
const char *strSource
); // C++ only
刚才的使用场景中的例子:strcpy_s(d, _countof(d), s);等同与如下表达式:
strcpy_s(d, s); 同样意味着s加上null后不能超过s的长度
如果s1max不确定时, 容易引起越界写 使用的代替方式如下:
strncpy_s:
errno_t strncpy_s(
char* strDest,
size_t numberOfElements,
const char* strSource,
size_t count
);
原理:
1:比较count和s1max count大则判断s1max是否比s2和null大;
2:count小则复制s2最多count个元素到s1
描述比strcpy_s多一条:如果count比s1max大 就必须保证s1max比s2加null大; 小就无所谓了
总结:
1:不管是strcpy_s还是strncpy_s s1max的意思都是指s1的max 虽然我们可以改 但最好不要改
2:尽量使用strncpy_s, 除了防止越界写(使用结论1就可以防止越界写), 还在可能出错的时候
提供一个优雅的处理方式(对着这点eg:strcpy_s 出错时程序直接退出)
strcpy_s:
#define _ _STDC_WANT_LIB_EXT1_ _1
#include <string.h>
errno_t strcpy_s(char * restrict s1, rsize_t s1max, const char * restrict s2);
Neithers1nors2shall be a null pointer. s1maxshall not be greater than RSIZE_MAX.
s1maxshall not equal zero. s1max shall be greater thanstrnlen_s(s2, s1max).
Copying shall not take place between objects that overlap.
s1和s2不为空 s1max不超过RSIZE_MAX且不能为0 s1max要比s2的个数大
msdn上有这么一句:
The strcpy_s function copies the contents in the address of strSource, including the terminating null character,
to the location specified by strDestination. The destination string must be large enough to hold the source string,
including the terminating null character. The behavior of strcpy_s is undefined if the source and destination strings overlap.
一句话就是s1max是s2带上空终止符 而s1max一定要比s1的大小小 不然怎么放下
string str_1 = "1234567890987654321";
char str_2[20] = {0};
strcpy_s(str_2, 18, str_1.c_str());
测试发现 strcpy_s的原理应该是:
1:比较s1max和strlen(s2)+1 至少保证s1max大于等于后者
2:复制数据到s1 不管s1的大小是否大于s1max 如果s1小于s1max 肯定是写过界
优点:s1max有效地限制了s2的大小 如果s2+1大于s1max 就直接报错了
缺点:s1max无法限制s1 如果s1比s1max小 可能出现越界写 这个后果更严重
使用场景: strcpy_s(d, _countof(d), s); 务必保证s里的长度加上null 要小于等于d的长度
其中s分为null结尾和非null结尾:非null结尾的加null后和s1max比较 带null的直接比较
扩展:
template <size_t size>
errno_t strcpy_s(
char (&strDestination)[size],
const char *strSource
); // C++ only
刚才的使用场景中的例子:strcpy_s(d, _countof(d), s);等同与如下表达式:
strcpy_s(d, s); 同样意味着s加上null后不能超过s的长度
如果s1max不确定时, 容易引起越界写 使用的代替方式如下:
strncpy_s:
errno_t strncpy_s(
char* strDest,
size_t numberOfElements,
const char* strSource,
size_t count
);
原理:
1:比较count和s1max count大则判断s1max是否比s2和null大;
2:count小则复制s2最多count个元素到s1
描述比strcpy_s多一条:如果count比s1max大 就必须保证s1max比s2加null大; 小就无所谓了
总结:
1:不管是strcpy_s还是strncpy_s s1max的意思都是指s1的max 虽然我们可以改 但最好不要改
2:尽量使用strncpy_s, 除了防止越界写(使用结论1就可以防止越界写), 还在可能出错的时候
提供一个优雅的处理方式(对着这点eg:strcpy_s 出错时程序直接退出)