【问题标题】:Unicode Compiler error on simple function简单函数上的 Unicode 编译器错误
【发布时间】:2011-06-19 06:46:40
【问题描述】:

叹息

我正在使用 Microsoft Visual Express C++ IDE。我最近从 DevC++ 过渡到了这个 IDE。

我有一个在 DevC++ 中完美运行的函数,但在 MSVC++ 中它不会因为 Unicode 而编译(我认为?)。我需要更改什么才能编译我的函数?

查看我得到的编译器错误的注释代码行

map <string, string> GetEvironmentVariablesEx()
{
   map <string, string> envVariables;
   char* environVar = GetEnvironmentStrings();  // Compile error: error C2440: 'initializing' : cannot convert from 'LPWCH' to 'char *'
   char* pos        = strchr( environVar, '\0' );

   // Skip over the "=::=::\0" of the environVar string
   if ( pos != NULL ) { environVar = ++pos; pos = strchr( environVar, '\0' ); }
   else return envVariables;

   while ( true )
   {
       char* delim    = strchr( environVar, '=' );
       if ( delim == NULL )
            break;

       string variable = string( environVar, strlen(environVar)-strlen(delim) );
       string value    = string( ++delim );

       envVariables.insert( pair<string, string>(variable, value) );
       environVar = ++pos;

       // find the "\0\0" that identifies the end of environVar
       if ( pos != NULL && *pos == 0 ) { break; }

       pos = strchr( environVar, '\0' );
   }

   FreeEnvironmentStrings( environVar ); 
   return envVariables;       
}

PS:因为这个应用程序是用 Unicode 编译的,这是否意味着它可以在 ANSII 计算机和 UNICODE 计算机上运行 - 所以我的应用程序可以在国际上运行?

【问题讨论】:

    标签: c++ visual-c++ compiler-errors


    【解决方案1】:

    Visual C++ 正在尝试编译您的程序以支持 Unicode。在后台,这是通过 #define-ing UNICODE_UNICODE 宏来完成的。这反过来又会导致您的程序使用 Win32 函数的 Unicode 变体。

    每个 Win32 函数(接受或返回字符串)都有两个变体。比如GetEnvironmentStrings其实就是两个函数:GetEnvironmentStringsAGetEnvironmentStringsWGetEnvironmentStrings 解析为其中之一,具体取决于是否定义了 UNICODE 宏。

    因此,您的程序正在为 Unicode 编译,编译器无法弄清楚如何获取 (Unicode) GetEnvironmentStringsW(这是 LPWCH -- 实际上是 WCHAR *)的结果并将其放入(ANSI)std::string.

    您可以执行以下操作之一(或组合):

    1. 将整个程序转换为 Unicode(开始使用 std::wstring)。
    2. 明确使用GetEnvironmentStringsA
    3. 改为为非 Unicode 重新编译。
    4. 利用 Windows 中的 TCHAR 支持。你需要define a tstring type

    这不是一个详尽的列表。

    回复:

    因为这个应用程序是用 Unicode 编译的,这是否意味着它可以在 ANSII 计算机和 UNICODE 计算机上运行 - 所以我的应用程序将能够在国际上运行?

    计算机不是 ANSI 或 Unicode。操作系统是。不支持 Unicode 的最后一个 Windows 版本是 Windows 3.11 for Workgroups。

    也就是说,仅针对 Unicode 进行编译并不能使您的应用程序能够在国际上运行。它可以正常工作,但 Unicode 仅涵盖字符集。您仍然需要担心翻译、日期和时间格式、数字格式、不同的日历。国际化、本地化和全球化不仅仅是启用 Unicode 支持。

    【讨论】:

    • 谢谢,最后一件事,C++ 这样做有价值吗? GetEvironmentVariablesEx()[L"USERNAME"].c_str();还是在尝试访问键值对之前必须将映射存储在变量中?
    • @user 您应该接受最佳答案。就是这个。
    【解决方案2】:

    您的项目是 UNICODE 构建并且您使用 ANSI 字符串,首先要做的是将您的 char 变量替换为 TCHAR 并重试。

    正如@David Heffernan 恰当地建议的那样,您将不得不切换到 wstring 并恰当地更改您使用的标准库中的库函数。

    【讨论】:

    • 仅仅使用 TCHAR 是不够的。您必须切换到 wstring 并更改您调用的 std lib 函数。
    • @David Heffernan:是的,正要编辑!为我+1。
    • 这将是一个好的开始,并允许您编译为 ANSI 或 Unicode。您还需要使用字符串库函数的“t”变体,例如 _tcschr() 而不是 strchr
    • TCHAR 仅用于应继续可用于charwchar_t 的代码,使其能够在各种旧Windows 版本上使用。如果不需要,只需选择其中一个并对此感到满意。
    【解决方案3】:

    您正在编译针对 Unicode 字符串但声明 ANSI 字符串变量的应用程序。如果您想要 Unicode,那么您需要使用宽字符、wstring 以及标准库中相应的字符串处理例程。

    如果您还没有准备好应对这种变化,那么将项目选项从 Unicode 更改为 MBCS,这是获得 ANSI 构建的稍微违反直觉的方式。

    【讨论】:

      【解决方案4】:

      这与您的程序能否在不同的 Windows 机器上正确运行无关 - 它与 Windows 进行的转换有关。一种以一个或多个 string 作为参数的 Windows API,它有 2 个版本:ANSI 和 Unicode。虽然并非所有函数都有 2 个变体(例如 ReadDirectoryChangesW,它是 Unicode-only)。

      当您调用 ANSI 版本时,Windows 需要将该 ANSI 字符串复制到 Unicode 字符串中。是的,它需要内存分配,将 1 字节 ANSI 字符转换为 2 字节 Unicode 字符。如果该函数将一个或多个字符串作为输出,则需要将 Unicode 转换为 ANSI。

      这显然会耗费时间和内存,并使您的程序变慢。此外,许多 ANSI 版本会/可能会修改传递的 ANSI 字符串,并且它会要求您 not 传递字符串常量。如果你传递字符串常量(比如硬编码的可执行路径到 CreateProcessA),它会导致一些 Win32 内存异常。

      因此最好将所有 ANSI 项目都转换为 Unicode。

      PS:字符串使用 _T、_TEXT 甚至 L 令人沮丧。为什么 VC++ 编译器不支持将所有 "strings" 视为 L"strings" 的选项? :[

      【讨论】:

      • 为什么 VC++ 编译器不支持将所有“字符串”视为 L“字符串”的选项?那么那将是 C++ 以外的其他语言。
      • 没有说服力。当“auto”是 C++ 语言的一部分时,它看起来像“var”(这不是!)。那么为什么不编译器选项将字符串视为 Unicode 字符串呢?在VC++中,'Language'下有很多选项——“Treat strings as Unicode”可以放!
      • 语言规则定义明确。就这么简单。
      • 我再次请求不同,“禁用语言扩展”适用于 MS 编译器。非常量数组大小支持由 GCC 提供。两者都不是 100% 符合“定义明确的语言规则”。
      • 所有这些供应商特定的扩展都是一个红润的噩梦
      猜你喜欢
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-21
      相关资源
      最近更新 更多