【问题标题】:Non-ASCII wchar_t literals under LLVMLLVM 下的非 ASCII wchar_t 文字
【发布时间】:2012-10-16 07:54:25
【问题描述】:

我已将 Xcode iOS 项目从 Xcode 3.2.6 迁移到 4.2。现在,当我尝试使用具有非 ASCII 字符的文字初始化 wchar_t 时,我收到了警告:

wchar_t c1;
if(c1 <= L'я') //That's Cyrillic "ya"

消息是:

MyFile.cpp:148:28:警告:字符 unicode 转义序列对其类型来说太长 [2] MyFile.cpp:148:28:警告:宽字符常量中的无关字符被忽略 [2]

并且文字没有按预期工作 - 比较失败。

我正在使用 -fshort-wchar 进行编译,源文件是 UTF-8 格式。 Xcode 编辑器可以正常显示文件。它在 GCC(包括 Xcode 3 在内的多种版本)上编译和工作,在 MSVC 上工作。有没有办法让 LLVM 编译器识别这些文字?如果没有,我可以在 Xcode 4 中回到 GCC 吗?

编辑:Snow Leopard 上的 Xcode 4.2 - 长话短说。

EDIT2:确认了一个全新的项目。文件扩展名无关紧要 - .m 文件中的行为相同。 -fshort-wchar 也不影响它。看来我必须回到 GCC,直到我可以升级到修复此问题的 Xcode 版本。

【问题讨论】:

  • 这是 Xcode 4 的哪个版本?您的项目设置使用什么编译器?
  • This 看起来像相关的错误。

标签: c++ ios xcode4 llvm wchar-t


【解决方案1】:

如果实际上源是 UTF-8,那么这不是正确的行为。但是我无法在最新版本的 Xcode 中重现该行为

MyFile.cpp:148:28: 警告:字符 unicode 转义序列对其类型来说太长 [2]

这个错误应该是指一个“通用字符名称”(UCN),它看起来像“\U001012AB”或“\u0403”。它表示转义序列表示的值大于封闭的文字类型能够容纳的值。例如,如果代码点值需要超过 16 位,则 16 位 wchar_t 将无法保存该值。

MyFile.cpp:148:28: 警告:宽字符常量中的无关字符被忽略 [2]

这表明编译器认为在一个宽字符文字中表示了多个代码点。例如。 L'ab'。行为是实现定义的,clang 和 gcc 都只使用最后一个代码点值。

您显示的代码不应触发其中任何一个,至少在 clang 中是这样。第一个是因为这只适用于 UCN,更不用说 'я' 很容易适合单个 16 位 wchar_t 的事实;第二个是因为他的源代码编码总是被认为是 UTF-8,它会将 'я' 的 UTF-8 多字节表示视为单个代码点。

您可以重新检查并确保源实际上是 UTF-8。然后你应该检查你使用的是最新版本的 Xcode。您也可以尝试在项目设置中切换编译器 > Compile for C/C++/Objective-C

【讨论】:

  • 我接受了,因为答案包含更新 Xcode 或将编译器切换回 GCC 的正确建议。后者绝对有效,前者为弗拉德工作。但这里真正的答案是 Jesse Good 的评论。
  • @SevaAlekseyev 好的,看起来您使用的 clang 版本是在 clang 迁移到使用 UTF-8 作为输入字符集之前的版本。不久前添加了对 UTF-8 字符和字符串文字的支持。
【解决方案2】:

不是答案,但希望是有用的信息——我无法用 clang 4.0 (Xcode 4.5.1) 重现问题:

$ uname -a
Darwin air 12.2.0 Darwin Kernel Version 12.2.0: Sat Aug 25 00:48:52 PDT 2012; root:xnu-2050.18.24~1/RELEASE_X86_64 x86_64
$ env | grep LANG
LANG=en_US.UTF-8
$ clang -v
Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix
$ cat test.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    wchar_t c1 = 0;
    printf("sizeof(c1) == %lu\n", sizeof(c1));
    printf("sizeof(L'Я') == %lu\n", sizeof(L'Я'));
    if (c1 < L'Я') {
        printf("Я люблю часы Заря!\n");
    } else {
        printf("Что за....?\n");
    }
    return EXIT_SUCCESS;
}

$ clang -Wall -pedantic ./test.c 
$ ./a.out 
sizeof(c1) == 4
sizeof(L'Я') == 4
Я люблю часы Заря!
$ clang -Wall -pedantic ./test.c -fshort-wchar
$ ./a.out 
sizeof(c1) == 2
sizeof(L'Я') == 2
Я люблю часы Заря!
$ 

使用 clang++ 观察到相同的行为(其中wchar_t 是内置类型)。

【讨论】:

    【解决方案3】:

    我没有回答您的具体问题,但想指出 llvm-gcc 已永久停产。根据我处理 Clang 和 llvm-gcc 以及 gcc 之间的 delta 的经验,Clang 在 C++ 规范方面通常是正确的,即使这种行为令人惊讶。

    【讨论】:

      猜你喜欢
      • 2011-06-08
      • 1970-01-01
      • 2015-11-11
      • 2014-06-12
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      相关资源
      最近更新 更多