C++中strcpy()函数和strcpy_s()函数的使用及注意事项

在编写C++程序时,不可避免会遇到strcpy()函数和其安全版本strcpy_s()函数,其实之所以会推出_s版本的函数,就是为了使编程更加安全,然而为了保证安全,也就会更容易使我们编写的代码“被报错”。所以这里来简略说一下strcpy()函数和strcpy_s()函数的使用及注意事项。

首先,我们知道原函数strcpy()函数和安全版本strcpy_s()函数都是存在于头文件<cstring>中的,所以程序一开始必须要有以下语句:

#include <cstring>

其次,原函数strcpy()函数是存在于标准名称空间std中的成员,所以要使用strcpy()函数,还需要加上以下语句:

using namespace std;

或者:

using std::strcpy;

或者在每次使用strcpy()函数时,前面加上名称空间:

std::strcpy(str1, str2);

但是对于最新的编辑器,往往你正常使用strcpy()函数,还是会报错,例如下面这个简单的例子:

 1 // strcpy.cpp -- test the strcpy function and strcpy_s function
 2  
 3 #include "stdafx.h"
 4 #include <iostream>
 5 #include <cstring>
 6  
 7  
 8 int main()
 9 {
10     char str1[20];
11     char str2[20];
12     std::cout << "Please enter str2: ";
13     std::cin.get(str2, 20);
14     std::strcpy(str1, str2);
15     std::cout << "str1 is " << "" " << str1 << "".
";
16     system("pause");
17     return 0;
18 }

正常来说,语法上没有任何问题,但是运行时,Visual Studio 2017 会报错,显示如下:

意义很简单,就是告诉你,strcpy()函数不安全,必须改为使用strcpy_s()函数,首先不管改成strcpy_s()函数之后会发生什么后续问题,其实从理论上来说,上面的代码语法上和逻辑上来说都是对的,那么怎么避免编辑器强制要求你使用安全版本呢?

其实解决方法有很多,单单是避免上图中的错误代码4996的情况,可以使用编辑器的选择性提供warning功能,在include语句前面加上下句:

#pragma warning( disable : 4996)

但是这种解决方法有时候不能解决问题,例如VS2017我就试过好像不行,那么我们就索性关闭warning功能就好了,完成这个任务的方法是在#include<stdio.h>的前面加上一句,如下所示:

1 #define _CRT_SECURE_NO_WARNINGS
2 #include <stdio.h>

VS2017里面,这句应该是加在头文件“stdafx.h”里面。

加完之后,再次运行相同的程序,就可以正常运行了,显示结果如下图所示:

那么解决了不使用安全版本的问题,接下来就来说一下使用安全版本的情况。

如果我们选择相信编辑器,那么我们就会把strcpy()函数改成使用strcpy_s()函数,改完之后运行首先会遇到以下错误:

这是因为之前使用strcpy()函数时,我们知道该函数是标准名称空间std的成员,而安全版本strcpy_s并不是该名称空间的成员,所以“std::”应该被去掉,去掉之后再次运行,就会正常运行了。

但是有时候,编辑器在你去掉“std::”还是会出现错误,错误说明是:1.没有与参数列表匹配的 重载函数"strcpy_s"实例;2."strcpy_s":函数不接受2个参数。

如下图所示:

这是因为strcpy_s()函数是有两个版本,用两个参数、三个参数都可以,只要可以保证缓冲区大小。
三个参数时:

1 errno_t strcpy_s( 
2 char *strDestination, 
3 size_t numberOfElements, 
4 const char *strSource 
5 );

两个参数时:

1 errno_t strcpy_s( 
2 char (&strDestination)[size], 
3 const char *strSource 
4 ); // C++ only 

所以,若我们使用new来分配储存空间时,就会出现上面说的不能保证缓冲区大小的问题了。

看下面的代码:

1 char * str;
2 str = new char[4];
3 strcpy_s(str, "C++");

语法来说没有什么问题,但是因为str的储存空间是使用new临时分配的,所以并不能保证缓冲区大小,点击运行就会出现上述的两种错误了。

这种情况的解决方法其实很简单,那就是不符合2个参数的版本就使用3个参数的版本呗。在两个str之间,加上一个参数,标识长度。

所以完整代码如下:

 1 // strcpy.cpp -- test the strcpy function and strcpy_s function
 2  
 3 #include "stdafx.h"
 4 #include <iostream>
 5 #include <cstring>
 6  
 7  
 8 int main()
 9 {
10     char str1[20];
11     char str2[20];
12     std::cout << "Please enter str2: ";
13     std::cin.get(str2, 20);
14     strcpy_s(str1, str2);
15     std::cout << "str1 is " << """ << str1 << "".
";
16     char * str;
17     str = new char[20];
18     strcpy_s(str, strlen(str1)+1, str1);
19     std::cout << "str is " << """ << str << "".
";
20     system("pause");
21     return 0;
22 }

这里分别使用了2个参数和3个参数的strcpy_s()函数版本。

后面使用3个参数的版本时,一般的做法就是将长度定为被复制的字符串长度+1,因为strlen()返回字符串长度,但是不包括字符串末尾的空字符,所以+1。

上述代码运行结果如下图所示:

以上就是strcpy()函数和strcpy_s()函数的基本使用和注意事项了,希望对大家有所帮助~

原文地址:https://www.cnblogs.com/ybqjymy/p/14171979.html