1,不使用strcpy和sprintf,它们可能导致缓冲区溢出
2,strncpy的用法
char *strncpy(char *dest, const char *src, size_t n);
标准用法:src串的长度应该小于dest缓冲区的大小,且n为dest缓冲区的大小减1或者更小,即至少留出一个位置给'\0'。(如果src串的长度大于或等于dest缓冲区的大小,则n应该为dest缓冲区的大小减1或者更小,否则将溢出。)
示例:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[5] = "";
char str2[10] = "";
char str3[15] = "";
char* p = "0123456789";
size_t np = 10;
// strncpy(str1, p, sizeof(str1)); // 源串长度大于目标buf的大小,且拷贝个数等于目标buf的大小,溢出
// printf("str1=%s/n", str1);
//
// strncpy(str1, p, np); // 源串长度大于目标buf的大小,且拷贝个数大于目标buf的大小,溢出
// printf("str1=%s/n", str1);
strncpy(str1, p, sizeof(str1) - 1); // 源串长度大于目标buf的大小,但是拷贝个数小于目标buf的大小,结果是拷贝了sizeof(str1)-1个字符,ok
printf("str1=%s/n", str1);
// strncpy(str2, p, sizeof(str2)); // 源串长度等于目标buf的大小,且拷贝个数等于目标buf的大小,溢出
// printf("str2=%s/n", str2);
//
// strncpy(str2, p, np); // 源串长度等于目标buf的大小,且拷贝个数等于源串长度,溢出
// printf("str2=%s/n", str2);
strncpy(str2, p, sizeof(str2) - 1); // 源串长度等于目标buf的大小,但是拷贝个数小于目标buf的大小,结果是拷贝了sizeof(str2)-1个字符,ok
printf("str2=%s/n", str2);
strncpy(str3, p, sizeof(str3)); // 源串长度小于目标buf的大小,且拷贝个数等于目标buf的大小,ok,标准用法
printf("str3=%s/n", str3);
strncpy(str3, p, np); // 源串长度小于目标buf的大小,且拷贝个数等于源串长度,ok,非标准用法
printf("str3=%s/n", str3);
return 0;
}
// g++ t.cpp -o t -g -Wall
/*
str1=0123
str2=012345678
str3=0123456789
str3=0123456789
*/
3,snprintf的用法
int snprintf(char *str, size_t size, const char *format, ...);
说明: 最多从源串中拷贝(size - 1)个字符到目标串中,再在后面加一个'/0'。
返回值: 若成功则返回源串的长度,若出错则返回负值。
标准用法:源串长度应该小于目标str缓冲区的大小,且size等于目标str缓冲区的大小。(如果源串长度大于或等于目标str缓冲区的大小,且size等于目标str缓冲区的大小,则只会拷贝目标str缓冲区的大小减1个字符,后加'\0';该情况下,如果size大于目标str缓冲区的大小则溢出。)
示例:
#include <stdio.h>
int main()
{
char str1[5] = "";
char str2[10] = "";
char str3[15] = "";
char* p = "0123456789";
size_t np = 10;
int n;
n = snprintf(str1, sizeof(str1), p); // 源串长度大于目标buf的大小,且拷贝个数等于目标buf的大小,只会拷贝sizeof(str1)-1个字符,后加'/0',ok,结果不是想要的
printf("str1=%s, n=%d/n", str1, n);
// n = snprintf(str1, np, p); // 源串长度大于目标buf的大小,且拷贝个数等于源串长度,溢出
// printf("str1=%s, n=%d/n", str1, n);
n = snprintf(str2, sizeof(str2), p); // 源串长度等于目标buf的大小,且拷贝个数等于目标buf的大小,只会拷贝sizeof(str2)-1个字符,后加'/0',ok,结果不是想要的
printf("str2=%s, n=%d/n", str2, n);
n = snprintf(str2, np, p); // 同上
printf("str2=%s, n=%d/n", str2, n);
n = snprintf(str2, 12, p); // 源串长度等于目标buf的大小,且拷贝个数大于目标buf的大小,只会拷贝整个源串,溢出
printf("str2=%s, n=%d/n", str2, n);
n = snprintf(str3, sizeof(str3), p); // 源串长度小于目标buf的大小,且拷贝个数等于目标buf的大小,会拷贝整个源串,后加'/0',ok,标准用法
printf("str3=%s, n=%d/n", str3, n);
n = snprintf(str3, np, p); // 源串长度小于目标buf的大小,且拷贝个数等于源串长度,只会拷贝np-1个字符,后加'/0',ok,结果不是想要的
printf("str3=%s, n=%d/n", str3, n);
return 0;
}
// g++ t.cpp -o t -g -Wall
/*
str1=0123, n=10
str2=012345678, n=10
str2=012345678, n=10
str2=0123456789, n=10
str3=0123456789, n=10
str3=012345678, n=10
*/
4,strnlen
size_t strnlen(const char *s, size_t maxlen);
说明:获取字符串s中的字符个数n,不包括结尾的'/0';如果n <= maxlen,则返回n,否则返回maxlen。
示例:
#include <stdio.h>
#include <string.h>
int main()
{
char* p = "0123456789";
size_t np = 10;
size_t n;
n = strnlen(p, 9);
printf("n=%d/n", n);
n = strnlen(p, np);
printf("n=%d/n", n);
n = strnlen(p, 11);
printf("n=%d/n", n);
return 0;
}
// g++ t.cpp -o t -g -Wall
/*
n=9
n=10
n=10
*/