int main() { char strHelloWorld1[] = { "hello" }; char strHelloWorld2[] = { "world1" }; char strHelloWorld3[MAX_LEN_NUM] = { 0 }; strncpy(strHelloWorld3, strHelloWorld2, 2); strcat(strHelloWorld2, "Welcome to C++"); return 0; }
Q: 对于这么一段代码,在VS运行程序时会出现下列警告,检查严格时会直接报错 This function or variable may be unsafe.
解决起来也容易,程序开头进行宏定义 #define _CRT_SECURE_NO_WARNINGS 或者 项目 - 属性 - 配置 - C/C++ - 预处理器 - 预处理器定义里添加:_CRT_SECURE_NO_WARNINGS。
strcat哪里不安全??
调试上述代码,会发现strHelloWorld2只有6字节,进行连接操作时,发生缓冲区溢出,影响了strHelloWorld1。
strcat_s和strcpy_s的简单用法
1、strcat_s
errno_t strcat_s(char * restrict dest,rsize_t destsz,const char * restrict src);
功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
参数
- strDestination : Null 终止的目标字符缓冲区。
- munberOFEIements:目标字符串缓冲区的大小。
- strSource:Null 终止的源字符串缓冲区。
返回值:
- 0:成功
- EINVAL:目标字符串或者源字符串没有初始化
- ERANGE:越界
如果dest <strlen(dest)+ strlen(src)+1 <= destsz所指向的字符数组的大小,则行为未定义;
2、strcpy_s
errno_t strcpy_s(char * restrict dest,rsize_t destsz,const char * restrict src);
- dest-指向要写入的字符数组的指针
- src-指向要复制的空终止字节字符串的指针
- destsz-写入的最大字符数,典型地为目标缓冲区的大小,理论上不能超过RSIZE_MAX
char s1[5]; // sizeof(s1) >= dest_size > strlen(src)
strcpy_s(s1, 4, "AA"); // "AA" // sizeof(s1) >= dest_size <= strlen(src)
strcpy_s(s1, 1, "AA"); // 程序异常退出 // sizeof(s1) >= dest_size > strlen(src)
strcpy_s(s1, sizeof(s1), "AA"); // "AA"
3、strnlen_s
strlen计算时,一定要确保字符数组是以空字符结束的,如果没有则可能沿着数组在内存中的位置不断向前寻找,知道遇到空字符才停下来。而strlen_s限制住了扫描范围所以不会出事。
声明:
size_t strnlen(const char *str, size_t numberOfElements);
参数:
str -- 要计算的字符串
numberOfElements -- 最大数量的字符进行检查
返回值:
如果在刚开始的numberOfElements长度里找到不到空字符,则返回numberOfElements。
如果字符串长度小于numberOfElements,且字符串结尾有空字符则返回字符串长度,如果结尾没有空字符,则返回numberOfElements。
#include "stdafx.h" #include <iostream> #include <cstring>
int main(){ char str[] = "Hello,world"; size_t len = strnlen_s(str, 5); std::cout << "length is " << len << std::endl; return 0; } 结果输出: length is 5 请按任意键继续. . .
不错的文档网站:https://cloud.tencent.com/developer/doc/1024
dest | - | 指向要写入的字符数组的指针 |
src | - | 指向要复制的空终止字节字符串的指针 |
destsz | - | 写入的最大字符数,典型地为目标缓冲区的大小 |