【问题标题】:what are non-unicode applications什么是非 unicode 应用程序
【发布时间】:2011-04-22 05:46:03
【问题描述】:

众所周知,在windows系统中,我们可以在“控制面板\时钟、语言和区域”中为非Unicode程序设置区域设置语言。但是本地语言对应用程序意味着什么?由于我的理解是一个应用程序是一个编译后的二进制可执行文件,它只包含机器码指令,没有数据,那么字符编码如何影响它们的运行呢?

一种猜测是,如果可执行文件在代码段中包含一些文字字符串,它将使用一些内部字符集对它们进行编码。如果字符集不是 unicode,那么它将显示垃圾。但是不是内部的Charset是固定的吗?就像在 Java 中一样,java 规范定义内部编码是 UTF-16。

希望有人能回答我的问题,

谢谢。

【问题讨论】:

  • 请记住,Unicode 并不意味着 UTF16,但在 Windows 上却意味着。他们应该在 15 年前就使用 UTF8,而这个问题就不存在了。
  • @Matt Joiner:实际上,这个问题仍然存在。请记住,我们在这里讨论的是 non-Unicode 程序。他们根本不关心 Unicode 程序是使用 UTF8 还是 UTF16。

标签: java c operating-system


【解决方案1】:

RichieHindle 正确解释了大多数 API 有两种变体,一个 *W (Unicode) 和一个 *A (ANSI) 变体。但在那之后他就有点不对劲了。

重要的是要知道*A 变体(例如MessageBoxA)只是*W 版本(例如MessageBoxW)的包装。他们获取输入字符串并将其转换为 Unicode;他们获取输出字符串并将它们转换回来。

在 Windows SDK 中,对于所有此类 A/W 对,都有一个 #ifdef UNICODE 块,因此 MessageBox() 是一个扩展为 MessageBoxA()MessageBoxW() 的宏。因为所有的宏都使用相同的条件,所以许多程序要么使用 100% *A 函数,要么使用 100% *W 函数。 “非Unicode”应用程序是那些定义UNICODE的应用程序,因此专门使用*A变体。

但是,没有理由不能混合搭配 *A 和 *W 函数。混合 *A 和 *W 函数的程序会被认为是“Unicode”、“非 Unicode”还是其他?其实,答案也是喜忧参半。当涉及到时钟、语言和区域设置时,应用程序在进行 *W 调用时被视为 Unicode 应用程序,而在进行 *A 调用时被视为非 Unicode 应用程序 - 该设置控制 *A 包装器的方式转换为 *W 调用。因此,在多线程程序中,您可以同时成为两者(!)

所以,回到 RichieHindle 的示例,如果您调用值为 (char)0xE4 的 *A 函数,包装器将转发到带有 L'ä'L'ה' 的 *W 函数,具体取决于此设置。如果您随后使用值 (WCHAR)0x00E4 直接调用 *W 函数,则不会发生转换。

【讨论】:

    【解决方案2】:

    Windows 有两种方法可以让程序与之对话,称为“ANSI API”和“Unicode API”,“非 Unicode 应用程序”是通过“ANSI API”而不是通过“ANSI API”与 Windows 对话的方法。 “Unicode API”。

    这意味着应用程序传递给 Windows 的任何字符串都只是一个字节序列,而不是 Unicode 字符序列。 Windows 必须决定该字节序列对应于哪些字符,而您正在谈论的控制面板设置就是它是如何做到的。

    例如,一个非 unicode 程序在设置为使用 Windows Western 的 PC 上输出值为 0xE4 的字节时将显示字符 ä,而为希伯来语设置的程序将显示字符ה

    【讨论】:

    • 而在“ANSI API”中,一个字节表示屏幕上的一个字符。在 Unicode 中,屏幕上的一个字符可以用多个字节表示。
    • @Amigable Clark Kant:并非总是如此——“双字节字符集”(请参阅​​msdn.microsoft.com/en-us/library/dd317794%28VS.85%29.aspx)仍然使用 ANSI API。否则在Unicode之前不可能有中文版的Windows!
    • 还应该注意的是,Microsoft 可以轻松地将 UTF-8 添加为支持的多字节字符集并解决整个问题,但他们拒绝这样做
    • @RichieHindle:很好的解释。正如您所说,当应用程序调用 Windows API 时,它只是传入“一个字节序列”。那么编码中的“字节序列”是否与其源代码相同?我的意思是如果源代码是用 UTF-8 编写的,那么它们就是 UTF-8;如果源代码是GBK,那么字节序列是GBK。这意味着 ANSI C 没有像 Java 那样的固定内部编码(utf-16)。
    • @Guoqin:不,C 没有为其源代码或字符串文字定义标准编码。非 Unicode 程序输出的字符串文字将包含与源代码中相同的字节,无论它使用什么编码。
    【解决方案3】:

    非 unicode 应用程序主要使用多字节编码,其中字符串由 char* 表示,而不是 wchar_t*:

    char* myString;
    

    通过更改使用的编码,您可以更改应用程序可用的字符集。

    而且大多数应用程序都包含指令和数据。

    【讨论】:

    • @Amigable Clark Kant:不,“多字节”对于 ANSI API 和使用 char 是正确的。例如,参见MultiByteToWideChar API,其中MultiByte 表示非Unicode,WideChar 表示Unicode。
    • Answers 和 cmets 应说明这是 Microsoft 创建的不正确术语。 Unicode 的主要编码是 UTF-8,一种多字节编码,并且存在宽字符编码不是 Unicode 的系统。事实上,有人可能会争辩说它不是 Windows 上的 Unicode,因为 Windows 的 wchar_t 太小而无法存储任意 Unicode 代码点...
    • @Alexander Rafferty:那么对于数据段,ANSI C 中使用的内部编码是什么?不是由 C 定义的,或者我们可以改变它?
    • @RichieHindle:MultiByte 表示多字节,WideChar 表示宽字符。有很多系统使用 utf-8 处理多字节字符,C 标准中没有规定宽字符应该是 Unicode 或 ISO/IEC 10646。
    • @Guoqin:我希望您不要将 ANSI C(大致相当于 ISO 9899,ISO C)与 Windows ANSI API 混淆,之所以这么称呼是因为 Windows 使用的一些代码页是基于草稿的ANSI 标准。
    猜你喜欢
    • 1970-01-01
    • 2021-06-25
    • 2010-12-11
    • 2010-12-28
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多