C++ 在UTF-8内部工作,然后仅在Windows中需要时转换为UTF-16是否存在任何危险?

C++ 在UTF-8内部工作,然后仅在Windows中需要时转换为UTF-16是否存在任何危险?,c++,windows,utf-8,cross-platform,utf-16,C++,Windows,Utf 8,Cross Platform,Utf 16,VisualStudio试图坚持使用tchars,当使用UNICODE选项编译时,tchars基本上会使用Windows和其他API的广泛版本 是否存在在应用程序内部使用UTF-8的危险(使用C++ STL更容易,也使跨平台代码更可读),然后当您需要使用任何OS API时,只转换为UTF-16?< /P> 我特别要求开发多个操作系统-不使用UTF-8的Windows和其他类似Mac的操作系统。由于UTF-8和UTF-16只是编码数字的两种方式(然后被解释为所谓的代码点或符号),来回转换没有错:没

VisualStudio试图坚持使用tchars,当使用UNICODE选项编译时,tchars基本上会使用Windows和其他API的广泛版本

是否存在在应用程序内部使用UTF-8的危险(使用C++ STL更容易,也使跨平台代码更可读),然后当您需要使用任何OS API时,只转换为UTF-16?< /P>


我特别要求开发多个操作系统-不使用UTF-8的Windows和其他类似Mac的操作系统。

由于UTF-8和UTF-16只是编码数字的两种方式(然后被解释为所谓的代码点或符号),来回转换没有错:没有信息丢失。因此,转换没有危险(当然,只要转换正确)。

危险在于UTF-8字符计数与ASCII字符计数不同。例如,U+24B62是单个Unicode字符,但扩展为4个UTF-8字节。(有关其他示例,请参见。)


如果不交替使用这两个函数,就不会有问题。

正如其他人所说,在内部使用UTF-8,然后在需要调用Windows函数时进行转换是没有危险的

但是,请注意,如果显示大量文本,每次转换so的成本可能会变得非常昂贵。(请记住,您不仅需要转换,还可能需要分配和释放缓冲区来保存临时转换字符串。)

我还应该指出,STL内置了广泛的字符支持,所以没有理由这么做。(std::wstring等人)


此外,只使用UTF-8对英语来说是不错的,但如果您计划支持东欧、阿拉伯语或亚洲字符集,那么您对文本的存储要求可能会比UTF-16更高(因为更多的字符需要存储三个或四个代码点)。如果你处理大量的文本,这可能只是一个问题,但这是一个值得考虑的问题——如果你要在任何时候通过网络连接来传输这个文本,那么这是双重的。

我假设你的项目不是关于文本处理、操作或转换的:对于文本处理,选择一种且仅选择一种编码要容易得多,在所有平台上都是相同的,然后在使用本机API时根据需要进行转换

但是,如果您的项目不是以文本处理/操作/转换为中心,那么在所有平台上限制UTF-8并不是最简单的解决方案

避免在Windows上使用
char
如果在Windows开发中使用
char
类型,那么所有WinAPI都将使用
char

问题在于Windows上的
char
类型用于“历史”应用程序,即unicode之前的应用程序

每个
char
文本都被解释为非Unicode文本,其编码/字符集由Windows用户选择,而不是由开发人员选择

意思:如果您认为您正在使用UTF-8,请将UTF-8
char
文本发送到WinAPI,以便在GUI(和文本框等)上输出,然后在阿拉伯语设置的Windows上执行代码(例如),然后您会看到漂亮的UTF-8字符文本不会被WinAPI正确处理,因为该窗口上的WinAPI认为所有
char
都将被解释为编码

如果您在Windows上使用
char
,您就放弃了Unicode,除非对WinAPI的每次调用都经过转换(通常通过GTK+、QT等框架,但它可能是您自己的包装函数)

优化是万恶之源,但在我看来,每次与Windows讨论时,将所有UTF-8文本从UTF-16转换为UTF-16似乎是一种毫无用处的悲观

备选方案:为什么不在所有平台上使用TCHAR? 您应该做的是使用
TCHAR
,为Linux/MacOS/任何东西提供一个类似于
TCHAR.h
的头(在原始
TCHAR.h
头中重新声明宏等),并为您要使用的标准库对象添加一个类似
TCHAR.h
的头。例如,我自己的
tstring.hpp
如下所示:

// tstring.hpp
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>

#ifdef _MSC_VER
#include <tchar.h>
#include <windows.h>
#else
#ifdef __GNUC__
#include <MyProject/tchar_linux.h>
#endif // __GNUC__
#endif


namespace std
{

#ifdef _MSC_VER

   // On Windows, the exact type of TCHAR depends on the UNICODE and
   // _UNICODE macros. So the following is useful to complete the
   // tchar.h headers with the C++ Standard Library's symbols.

   #ifdef UNICODE

      typedef              wstring        tstring ;
      // etc.
      static wostream &    tcout          = wcout ;

   #else // #ifdef UNICODE

      typedef              string         tstring ;
      // etc.
      static ostream &     tcout          = cout ;

   #endif // #ifdef UNICODE

#else // #ifdef _MSC_VER

    #ifdef __GNUC__

    // On Linux, char is expected to be UTF-8 encoded, so the
    // following simply maps the txxxxx type into the xxxxx
    // type, forwaking the wxxxxx altogether.
    // Of course, your mileage will vary, but the basic idea is
    // there.

    typedef                string         tstring ;
    // etc.
    static ostream &       tcout          = cout ;

    #endif // __GNUC__

#endif // #ifdef _MSC_VER

} // namespace std
//tstring.hpp
#包括
#包括
#包括
#包括
#ifdef硕士学位
#包括
#包括
#否则
#ifdef__GNUC__
#包括
#endif/\uu GNUC__
#恩迪夫
名称空间标准
{
#ifdef硕士学位
//在Windows上,TCHAR的确切类型取决于UNICODE和
//_UNICODE宏。因此,以下内容对于完成
//tCHAR.H头文件,带有C++标准库的符号。
#ifdef UNICODE
类型定义wstring tstring;
//等等。
静态wostream&tcout=wcout;
#else/#ifdef UNICODE
typedef字符串tstring;
//等等。
静态ostream&t输出=cout;
#endif/#ifdef UNICODE
#else/#ifdef(理学硕士)版本
#ifdef__GNUC__
//在Linux上,字符应该是UTF-8编码的,因此
//下面简单地将txxxxx类型映射到xxxxx
//键入,用于完全唤醒wxxxxx。
//当然,你的里程数会有所不同,但基本的想法是
//在那里。
typedef字符串tstring;
//等等。
静态ostream&t输出=cout;
#endif/\uu GNUC__
#endif/#ifdef(MSC)VER
}//名称空间std
Discplaimer:我知道,在std中声明东西是很不好的,但是我除了在这个特定的主题上学究气之外还有其他事情要做

使用这些标头,可以使用C++标准库与TCHAR 设施,即使用<代码> STD::TSHIG/<代码>,将其编译为<代码> STD::WSTRIN