跨平台C++:跨平台使用本机字符串编码还是标准化?

Jes*_*per 10 c++ linux windows unicode cross-platform

我们特别关注Windows和Linux开发,并提出了两种似乎都有其优点的不同方法.Windows中的自然unicode字符串类型是UTF-16,linux中是UTF-8.

我们无法决定最佳方法:

  1. 在我们所有的应用程序逻辑(和持久数据)中标准化其中一个,并使其他平台进行适当的转换

  2. 将OS的自然格式用于应用程序逻辑(从而调用OS),并仅在IPC和持久性点进行转换.

对我来说,他们似乎都和对方一样好.

won*_*ice 6

和linux中的UTF-8.

对于现代Linux来说,这几乎是正确的.实际上编码取决于使用的API或库.一些硬编码使用UTF-8.但有些读取LC_ALL,LC_CTYPE或LANG环境变量来检测要使用的编码(如Qt库).所以要小心.

我们无法决定是否采用最佳方法

像往常一样取决于.

如果90%的代码是以平台特定的方式处理特定于平台的API,那么显然最好使用特定于平台的字符串.作为示例 - 设备驱动程序或本机iOS应用程序.

如果90%的代码是跨平台共享的复杂业务逻辑,显然最好在所有平台上使用相同的编码.例如 - 聊天客户端或浏览器.

在第二种情况下,您可以选择:

  • 使用提供字符串支持的跨平台库(例如,Qt,ICU)
  • 使用裸指针(我认为std :: string也是"裸指针")

如果使用字符串是应用程序的重要组成部分,那么为字符串选择一个漂亮的库是一个很好的举措.例如,Qt有一组非常可靠的类,涵盖了99%的常见任务.不幸的是,我没有ICU经验,但它看起来也很不错.

在为字符串使用某些库时,只有在使用外部库,平台API或通过网络(或磁盘)发送字符串时才需要关心编码.例如,许多Cocoa,C#或Qt(都具有可靠的字符串支持)程序员对编码细节知之甚少(这很好,因为他们可以专注于他们的主要任务).

我使用字符串的经验有点具体,所以我个人更喜欢裸指针.使用它们的代码非常便携(从某种意义上说,它可以很容易地在其他项目和平台中重用),因为它具有较少的外部依赖性.它也非常简单快速(但可能需要一些经验和Unicode背景来感受).

我同意裸指针方法不适合所有人.这时很好:

  • 您使用整个字符串并进行拆分,搜索,比较是一项罕见的任务
  • 您可以在所有组件中使用相同的编码,并且仅在使用平台API时才需要转换
  • 您支持的所有平台都具有以下API:
    • 从您的编码转换为API中使用的编码
    • 从API编码转换为代码中使用的编码
  • 指针在您的团队中不是问题

从我的一点点具体经验来看,它实际上是一个非常常见的案例.

使用裸指针时,最好选择将在整个项目(或所有项目)中使用的编码.

从我的角度来看,UTF-8是最终的赢家.如果您不能使用UTF-8 - 使用字符串库或平台API作为字符串 - 它将为您节省大量时间.

UTF-8的优点:

  • 完全ASCII兼容.任何ASCII字符串都是有效的UTF-8字符串.
  • C std库适用于UTF-8字符串.(*)
  • C++ std库适用于UTF-8(std :: string和friends).(*)
  • 传统代码适用于UTF-8.
  • 相当的任何平台都支持UTF-8.
  • 使用UTF-8可以更轻松地进行调试(因为它与ASCII兼容).
  • 没有Little-Endian/Big-Endian一塌糊涂.
  • 你不会发现一个经典的错误"哦,UTF-16并不总是2个字节?".

(*)直到你需要进行词汇比较,转换大小写(toUpper/toLower),更改规范化形式或类似的东西 - 如果你这样做 - 使用字符串库或平台API.

缺点值得怀疑:

  • 中文(以及代码点数大的其他符号)比UTF-16更紧凑.
  • 更难(实际上有点)迭代符号.

所以,我建议使用UTF-8作为不使用任何字符串库的项目的通用编码.

但编码并不是您需要回答的唯一问题.

正常化这样的东西.简单来说,一些字母可以用几种方式表示 - 比如一个字形或者像不同字形的组合.与此相关的常见问题是大多数字符串比较函数将它们视为不同的符号.如果您从事跨平台项目,选择标准化表格之一作为标准是正确的举措.这样可以节省您的时间.

例如,如果用户密码包含"йёжиг",则在Mac上输入(主要使用规范化表格D)和在Windows上(大多数喜欢规范化表格C)时,它将以不同的方式表示(在UTF-8和UTF-16中).因此,如果用户在Windows下注册了这样的密码,那么他在Mac下登录就会出现问题.

另外我不建议使用wchar_t(或仅在Windows代码中使用它作为UCS-2/UTF-16字符类型).wchar_t的问题在于没有与之关联的编码.它只是一个比普通char更大的抽象宽字符(Windows上为16位,大多数为*nix时为32位).