Itoa 和不同的字符集 c++ visual studio 2013

Itoa and different character sets c++ visual studio 2013

我的代码:

    m_ListCtrlCandidates.InsertItem(i, _itoa_s(candidate[i].ID, (char*)(LPCTSTR)str, 10));
    m_ListCtrlCandidates.SetItemText(i, 1, _itoa(candidate[i].FingerNumber, (char*)(LPCTSTR)str, 10));
    m_ListCtrlCandidates.SetItemText(i, 2, _itoa(candidate[i].SampleNumber, (char*)(LPCTSTR)str, 10));
    m_ListCtrlCandidates.SetItemText(i, 3, _itoa(candidate[i].ConfidenceLevel, (char*)(LPCTSTR)str, 10));

错误:

Error   2   error C4996: '_itoa': This function or variable may be unsafe. Consider using _itoa_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    d:\documents\visual studio 2013\projects\gatekeeper\gatekeeper\gatekeeperdlg.cpp    416 1   Gatekeeper

我使用的 SDK 在其示例中包含以下代码。它将潜在的匹配项添加到对话框中的列表中。最初我将我的项目设置为 unicode 并更新了代码以使其工作。这给我带来了麻烦,所以我查看了示例代码,发现它的字符集是空白的。所以我改变了我的,现在我得到了这个错误。

如果我将其切换为 _itoa_s,我会收到该函数不接受 3 个参数的错误。所以我想我错过了大小参数,但我不确定它应该是什么大小。此外,当保留为 _itoa 时,它在示例代码中编译得很好。

我真的很想用 Unicode 保存它。使用 _wtoi 而不是 atoi 在其他地方有所帮助。这个案例有类似的东西吗?

I'm using an SDK that has the following code in their sample.

真不幸!

_itoa(candidate[i].FingerNumber, (char*)(LPCTSTR)str, 10)

我猜你正在使用 MFC,str 是一个 CString,而你正在调用 CListCtrl::SetItemText

CString 上的 (LPCTSTR) 运算符获取指向保存字符串数据的底层缓冲区的指针。那是一个 const TCHAR*,所以如果你在 ANSI 模式下编译,这是一个指向字节的 const char* 指针;在 Unicode 模式下,它是 const wchar_t* 指向 16 位代码单元的指针。

将其转换为非常量 char* 并要求 _itoa 写入它是一个非常糟糕的主意。这会覆盖 CString 中原来的内容,如果数字足够大,结果字符串比 CString 中原来的字符串长,你可能会写到数组的末尾,导致内存不足腐败浩劫。

在 Unicode 模式下将其转换为 char* 甚至更奇怪,因为您使用 wchar_t 数组作为 char* 字节的存储。而 SetItemText() 在 Unicode 模式下肯定会期望得到 wchar_t 个字符吗?

Using _wtoi instead of atoi helped in other places. Is there something similar

_itow 作为 _itoawchar_t 类似物存在。 (至少在 VS 中。这两个函数本身都不是标准的 C[++]。)

您可以打开 #ifdef _UNICODE 并调用 _itoa_itow 以匹配 TCHAR 的任何类型。但是,除非您出于某些遗留原因真的需要支持一个古老的纯 ANSI 构建,否则现在没有太多理由为 TCHAR 切换而烦恼。您通常可以坚持使用 Unicode 模式并使用基于 wchar_t 的文本字符串。

error C4996: '_itoa': This function or variable may be unsafe.

Microsoft 弃用了一些将可变数量的内容写入预分配缓冲区的 C 函数,因为缓冲区很容易太短,导致上述内存损坏恐怖。过去,这一直是应用程序中无数安全问题的原因,因此最好避免。

不幸的是,警告 4996 实际上弃用了一些并不真正危险的标准函数,这非常令人厌烦,特别是因为建议作为替代的 _s 版本通常不受其他编译器支持。

在这种情况下,尽管 MS 是正确的,但 _itoa 并不是很安全。要安全地使用它,您必须为您传递的类型的最长可能整数分配一个足够大的缓冲区,而且很容易出错。

If I switch it to _itoa_s I get the error that the function doesn't take 3 arguments. So I guess I'm missing the size argument, but I'm not sure what size it is suppose to be

然而,在要写入的指针末尾有许多元素可用。所以目前这将取决于 CString 的长度,你正在窃取其缓冲区。但这样做不是一个好主意。您可以分配自己的缓冲区:

wchar_t str[8];
_itow_s(candidate[i].FingerNumber, str, 8, 10);

这是安全的,但如果 FingerNumber 超过 7 位数字仍然会失败(错误号 EINVAL),因为没有 space 来存储它们(包括 [=42= ]终结者)。

itoa 这样的将变量内容写入缓冲区的函数通常非常难看。如果您可以将现代 C++ 与 STL 一起使用,则可以使用更简单、更安全的字符串处理方法,例如:

#include <string>

std::wstring fingers = std::to_wstring(candidate[i].FingerNumber);
m_ListCtrlCandidates.SetItemText(i, 1, fingers.c_str());

(尽管这与老式 MFC 和 CString 的混合程度如何是另一个问题。)