使用 strcpy_s 将字符串复制到字符*

Using strcpy_s to copy string to char*

本文关键字:复制 字符 字符串 strcpy 使用      更新时间:2023-10-16

我知道当你使用strcpy_s时,你应该提供目标字符串的大小作为第二个参数。但是,如果目标字符串是字符*,那么我不确定我做得是否正确。我有三个例子:

char* dest = new char;
// Example 1
CString strTemp = "Bob";
strcpy_s(dest, strTemp.GetLength() + 1, strTemp);   
// Example 2
strcpy_s(dest, strlen("Jose")+1, "Jose");
// Example 3 
char* c = new char;
c = "Richard";
strcpy_s(dest, strlen(c) + 1,c);        

这一切都正确吗?

在所有三个示例中,您传递的是字符串的大小。您应该传递目标缓冲区的大小,以便strcpy_s可以验证不会有缓冲区溢出。

传递源字符串的大小会破坏该检查。strcpy_s已经知道源字符串的大小;它可以像你一样做strlen(src)。它不能做的是自动检测目标缓冲区的大小。需要告诉它的大小。

const int SIZE = 2048; // an arbitrary large number
char* dest = new char[SIZE];
std::errno_t result = strcpy_s(dest, SIZE, src);   
if (result != 0) {
// error
}

您的所有示例都应如下所示:

  • dest指向的不是单个字符,而是大量字符数组。
  • 第二个参数是目标缓冲区的大小。
  • 确保检查返回代码是否存在错误。

注意:尽可能避免在C++中使用 C 字符串。使用std::string要好得多。它会为你处理所有这些混乱。您不必处理内存分配或担心缓冲区溢出。

请注意,您应该为目标分配正确的大小,因此请替换

分配一个字符的char* dest = new char;

char* dest = new char[strlen(strTemp)+1];.

请注意,cString不是一种类型,因此请替换CString strTemp = "Bob";char* strTemp = "Bob";const char* strTemp = "Bob";(最后一个相当于auto strTemp = "Bob";(。

请注意,c style strings 不是objects因此strTemp.GetLength()无效。将其替换为strlen(strTemp)并包含包含该函数的标头<cstring>strlen()

最后,您的代码应如下所示

#include<iostream>
#include<cstring>
using namespace std;
int main(){
auto strTemp = "Bob";
char* dest = new char[strlen(strTemp)+1];
strcpy_s(dest, strlen(strTemp) + 1, strTemp);   
cout<<dest;
}

这都是正确的吗?

没有一个例子是正确的。

char* dest = new char;

您已分配单个char。它可以表示的唯一字符串是空字符串。

char* c = new char;
c = "Richard";

通过将c分配给其他位置的点,您丢失了new返回的指针值。因此,您无法再将该值传递给delete。这称为内存泄漏。

此外,由于 C++11 起,这是格式不正确的,因为字符串文字不再可转换为指向非常量字符的指针。 格式错误意味着编译器不需要编译程序,而是需要向您发出诊断消息,通知您格式不正确。

strcpy_s(dest, strlen(c) + 1,c);

您应该传递目标缓冲区的大小,而不是源数据的大小。在这种情况下,目标缓冲区太小,但由于您传递了错误的值,因此不会捕获错误,并且行为未定义。

正如我所提到的,传递目标缓冲区的大小:

auto error = strcpy_s(dest, 1, "Richard");

这安全地导致错误而不是未定义的行为 - 或者它可能安全地中止程序或根据实现执行其他操作。您可以控制约束处理程序以具有所需的行为。

当然,您可能希望分配足够的内存,以便副本正常工作:

std::size_t destsz = 1024;
char* dest = new char[destsz];

您知道分配的大小。只需将其传递给strcpy_s

auto error = strcpy_s(dest, destsz, "Richard");

不要忘记清理:

delete[] dest;

附言C++标准库不提供strcpy_s。这是一个非标准功能。它仅在 C 语言中是标准的(但对于提供它的实现来说是可选的(。

PSS 不要使用new来分配字符串。在C++中使用std::string。使用std::string您可以像这样复制:

std::string c = "Richard";
std::string dest = c;

使用这种方法泄漏内存或制造更严重的错误将更加困难。

如果在将字符串复制到其中之前分配内存,使用字符串复制函数会显示混乱的思维,导致公然浪费:只需使用memcpy()(或std:copy_n()(。

strcpy_s()需要指向目标的指针、目标缓冲区大小和指向源的指针。
如果您猜测缓冲区大小是从源代码派生的缓冲区大小,而不是知道它,请使用strcpy()而不是那种复杂的方式来(希望(编写相同的效率较低。

总之,你所有的使用都是错误的。

顺便说一句:
new char分配一个单独的char,而不是一个适当大小的数组。请改用new char [n]
你真的需要复制字符串,还是实际上只是传递一个指针?
进程范围的约束处理程序不需要执行所需的操作。或者实际上任何有用的东西。