【问题标题】:Disable warning in MSVC++2010在 MSVC++2010 中禁用警告
【发布时间】:2011-09-20 09:38:59
【问题描述】:

我有以下代码:

/** Stupidly copies unicode chars into normal chars. */
std::string wstring2string(__in  const std::wstring& s)
{
    std::string temp(s.length(), ' ');
#pragma warning(push)
#pragma warning(disable: 4244) // possible loss of data
    std::copy(s.begin(), s.end(), temp.begin());
#pragma warning(pop)
    return temp;
}

我的编译器仍然显示警告 C4244:

1>c:\program files\microsoft visual studio 10.0\vc\include\xutility(2144): warning C4244: '=': Konvertierung von 'const wchar_t' in 'char', möglicher Datenverlust
1>          c:\program files\microsoft visual studio 10.0\vc\include\xutility(2165): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "_OutIt std::_Copy_impl<_InIt,_OutIt>(_InIt,_InIt,_OutIt,std::_Nonscalar_ptr_iterator_tag)".

(英文:“将const wchar_t转换为char,可能会丢失数据,参见刚刚编译的函数模板的实例化参考……”)。

如何禁用它?!

【问题讨论】:

  • 只是好奇:您确定忽略此警告是个好主意吗? wstring sstring temp 的编码呢?

标签: c++ visual-studio-2010 visual-c++ warnings


【解决方案1】:

试着把你的函数改成这样(没有可用的 C++ 编译器来检查它是否编译):

std::string wstring2string(__in const std::wstring& s)
{
    size_t bufferSize;

    // first call to wcstombs_s to get the target buffer size
    wcstombs_s(&bufferSize, NULL, 0, ws.c_str(), ws.size());

    // create target buffer with required size
    char* buffer = new char[bufferSize];

    // second call to do the actual conversion
    wcstombs_s(&bufferSize, s.c_str(), bufferSize, ws.c_str(), ws.size());

    string result(buffer, bufferSize);
    delete[] buffer;
    return result;
}

(受 dario_ramos 回答的启发)

就像您在 Windows 上一样,您甚至可以使用 Windows API 函数 WideCharToMultiByte,它的作用基本相同,但允许您指定目标编码。

【讨论】:

  • 我将在我的解决方案中尝试这个,如果它有效,我将删除我的答案以支持这个
【解决方案2】:

当我想这样做时,我只需将#pragma warning(disable, 2422) 放在有问题的.cpp 文件的顶部,在#include 之后。但如果我是你,我会尝试解决警告,而不是把它扫到地毯下。抛弃 constness 可能会导致未定义的行为。

要解决警告,请尝试以下操作(我们在解决方案中使用此功能):

string wtoString( const wchar_t *ws ){
        size_t bufferSize = (wcslen(ws) + 1) * sizeof(wchar_t);
        char * buffer = new char[ bufferSize ];
        size_t convertedChars;
        wcstombs_s( &convertedChars, buffer, bufferSize, ws, _TRUNCATE);
        string result(buffer);
        delete[] buffer;
        return result;
 }

调整它以接收 const wstring&,考虑到当你为 wstring() 调用 c_str() 时,你会得到一个 const wchar_t*,这应该很容易

编辑:现在我再看一遍,如果将 RAII 用于缓冲区局部变量,则可以进一步改进。以防万一。

编辑:更正代码以考虑字符大小

【讨论】:

  • 你能再精确一点吗?我不认为const 会造成问题,无论如何都会复制这些值,因此无法修改原始值——这不是 16 到 8 位的数字转换吗?我也很感谢有关如何解决警告本身的一些指导。
  • 好的,用如何解决这个问题的代码示例更新了我的答案
  • 小心!此解决方案不一定转换整个输入缓冲区。输入字符串中的单个 wchar_t 可以转换为多个 8 位字符。但是,当目标字符串已满时,该函数将停止工作。
  • 我不明白,你能给我一个导致你说的失败的输入的例子吗?
  • 正确的解决方案是调用 wcstombs_s 两次。第一次获得所需的字节数,第二次进行实际转换。我添加了另一个答案来证明这一点(我没有设法在评论中获得代码)
【解决方案3】:

只有在包含字符串 h-file 之前禁用它时才会显示警告。考虑到这种行为的原因,我猜这是特定于模板的问题。当包含模板类时,编译器会进行某种预编译。只有在模板被实例化时才进行完整编译。看起来 VC++ 编译器保留了预编译阶段的警告设置,并且在实例化之前更改它们没有帮助。

【讨论】:

    【解决方案4】:

    要消除此警告,您需要在包含该函数的头文件周围添加#pragma warning...。在您的情况下,这是 xutility。它包含在多个其他文件中。所以会很难找到。不过你可以这样试试。

    #pragma warning(push)
    #pragma warning(disable: 4244) // possible loss of data
    #include <xutility>
    #pragma warning(pop)
    Your includes go here...
    std::string wstring2string(__in  const std::wstring& s)
    {
        std::string temp(s.length(), ' ');
        std::copy(s.begin(), s.end(), temp.begin());
        return temp;
    }
    

    除此之外,我建议进行正确的转换。例如查看ICU 或至少使用标准中的功能。例如。 mbstowcs

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-17
      • 1970-01-01
      • 2014-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多