注意事项

由于 IBM® i 的缺省环境主要是 EBCDIC 环境,因此在应用程序中使用 UTF 支持时,您必须了解本主题中描述的情况。

如果程序或服务程序有一些使用 UTF 支持编译的模块以及一些在没有 UTF 支持的情况下编译的模块,那么必须注意确保不会发生意外的不匹配。 宽字符和宽字符串对于非 UTF 模块是两个字节大小,对于 UTF 模块是四个字节大小,因此在模块之间共享宽字符可能无法正常工作。 窄 (非宽) 字符和字符串在非 UTF 模块的作业 CCSID 和 UTF 模块的 CCSID 1208 中,因此在模块之间共享窄字符也可能无法正确工作。

每当执行 setlocale() 以将语言环境设置为不同的 CCSID 时,都应该清空标准输出文件,以避免包含多个 CCSID 的字符数据出现缓冲问题。 由于缺省情况下缓冲了 stdout 行,因此如果每个输出行都以换行符结束,那么不会发生问题。 但是,如果未执行此操作,那么输出可能不会按预期显示。 以下示例说明了问题。
#include <stdio>
#include <locale.h>

int main() {
   /* This string is in CCSID 1208 */
   printf("Hello World");

   /* Change locale to a CCSID 37 locale */
   setlocale(LC_ALL, "/QSYS.LIB/EN_US.LOCALE");
   #pragma convert(37)

   /* This string is in CCSID 37 */
   printf("Hello World\n");

   return 0;
}

在这种情况下,第一个 printf() 导致将 CCSID 1208 字符串 Hello World 复制到 stdout 缓冲区。 在完成 setlocale() 之前,应清空 stdout 以将该字符串复制到屏幕。 第二个 printf() 导致将 CCSID 37 字符串 Hello World \n 复制到 stdout 缓冲区。 因为尾部换行符,缓冲区在该点被冲刷,整个缓冲区被复制到屏幕上。 因为当前语言环境的 CCSID 是 37 ,并且屏幕可以处理 CCSID 37 而没有问题,所以将复制整个缓冲区而不进行转换。 CCSID 1208 字符显示为不可读字符。 如果已完成清空,那么 CCSID 1208 字符将已转换为 CCSID 37 并且已正确显示。

几乎所有运行时函数都已修改为支持 UTF ,但有少数没有。 处理异常处理的函数和结构 (例如, _GetExcData() 函数, _EXCP_MSGID 变量和异常处理程序结构 _INTRPT_Hndlr_Parms_T) 由操作系统提供,而不是由运行时提供。 它们严格为 EBCDIC。 getenv()putenv() 函数仅处理 EBCDIC。 QXXCHGDA()QXXRTVDA() 函数仅处理 EBCDIC。 argvenvp 参数也是仅 EBCDIC。

某些记录 I/O 函数 (即以 _R 开头的函数) 不完全支持 UTF。 不支持 UTF 的函数有 _Rformat()_Rcommit()_Racquire()_Rrelease()_Rpgmdev()_Rindara()_Rdevatr()。 当使用 UTF 选项进行编译时,它们可用,但它们仅接受并生成 EBCDIC。 此外, _R 函数返回的结构中的任何字符数据都将采用 EBCDIC 而不是 UTF。

尚未修改其他操作系统功能以支持 UTF。 例如,集成文件系统功能 (例如 open()) 仍接受作业 CCSID。 其他操作系统 API 仍接受作业 CCSID。 对于 UTF 应用程序,需要使用 QTQCVRT , iconv()#pragma convert或其他方法将提供给这些函数的字符和字符串转换为作业 CCSID。