4

此代码在 Xcode 的先前版本中编译。我更新了 Xcode,现在编译失败。我猜我的代码有问题。下面代码中的问号是根据 ISO-8859-1 (0xF6) 编码的 o-umlaut (ö) ——我们习惯称这个上位(或扩展)ASCII。我猜编译错误与为clang迁移到UTF-8输入编码有关?

$ xcrun -sdk macosx10.8 -run clang -v
Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.2.0

$ cat test.c
#include <stdio.h>
int main( int argc, char** argv )
{
    fprintf( stderr, "?\n" );
    return 0;
}

$ xcrun -sdk macosx10.8 -run clang -o test test.c 
test.c:4:23: warning: illegal character encoding in string literal [-Winvalid-source-encoding]
    fprintf( stderr, "<F6>\n" );
                      ^~~~
1 warning generated.
4

1 回答 1

8

因此,最新 Xcode (4.6) 中的 clang 似乎接受 UTF-8 编码并抱怨高位(或扩展)ASCII,因为根据ISO-8859-1的通用字符集 (UCS) 代码点的高位 ASCII混合到您的source 不会产生正确的 UTF-8 编码。我没有检查发行说明以验证新的 clang 是否需要 UTF-8,但我将源代码更改为具有正确的 UTF-8 编码的小 o-umlaut,并且它已编译。

0xF6 或 246 是小 o-umlaut 的 UCS 代码点。但是,要以 UTF-8 对其进行正确编码,您不能只将 0xF6 放在文件中的单个字节中。正确的 UTF-8 编码是两个字节:0xC3 0xB6。请参阅下面的详细信息。所以破解打开你最喜欢的十六进制编辑器,用两个字符替换一个 0xF6 字符:0xC3 0xB6。

这是一个很棒的十六进制编辑器:Hex Fiend

那么,如果您的问题角色不是 o-umlaut 怎么办?我列出了一些常见字符的列表,但您可以按照以下步骤查找任何其他 UTF-8 编码来解决您的特定问题:

| Char | ISO-8859-1 |   UTF-8   |
| ---- | ---------- | --------- |
|  ©   |    0xA9    | 0xC2 0xA9 |
|  ®   |    0xAE    | 0xC2 0xAE |
|  Ä   |    0xC4    | 0xC3 0x84 |
|  Å   |    0xC5    | 0xC3 0x85 |
|  Æ   |    0xC6    | 0xC3 0x86 |
|  Ç   |    0xC7    | 0xC3 0x87 |
|  É   |    0xC9    | 0xC3 0x89 |
|  Ñ   |    0xD1    | 0xC3 0x91 |
|  Ö   |    0xD6    | 0xC3 0x96 |
|  Ü   |    0xDC    | 0xC3 0x9C |
|  ß   |    0xDF    | 0xC3 0x9F |
|  à   |    0xE0    | 0xC3 0xA0 |
|  á   |    0xE1    | 0xC3 0xA1 |
|  â   |    0xE2    | 0xC3 0xA2 |
|  ä   |    0xE4    | 0xC3 0xA4 |
|  å   |    0xE5    | 0xC3 0xA5 |
|  æ   |    0xE6    | 0xC3 0xA6 |
|  ç   |    0xE7    | 0xC3 0xA7 |
|  è   |    0xE8    | 0xC3 0xA8 |
|  é   |    0xE9    | 0xC3 0xA9 |
|  ê   |    0xEA    | 0xC3 0xAA |
|  ë   |    0xEB    | 0xC3 0xAB |
|  ì   |    0xEC    | 0xC3 0xAC |
|  í   |    0xED    | 0xC3 0xAD |
|  î   |    0xEE    | 0xC3 0xAE |
|  ï   |    0xEF    | 0xC3 0xAF |
|  ñ   |    0xF1    | 0xC3 0xB1 |
|  ò   |    0xF2    | 0xC3 0xB2 |
|  ó   |    0xF3    | 0xC3 0xB3 |
|  ô   |    0xF4    | 0xC3 0xB4 |
|  ö   |    0xF6    | 0xC3 0xB6 |
|  ù   |    0xF9    | 0xC3 0xB9 |
|  ú   |    0xFA    | 0xC3 0xBA |
|  û   |    0xFB    | 0xC3 0xBB |
|  ü   |    0xFC    | 0xC3 0xBC |
|  ÿ   |    0xFF    | 0xC3 0xBF |

只有较低的 ASCII(7 位字符)可以编码为 UTF-8 中的单个字符。请参阅http://en.wikipedia.org/wiki/UTF-8

长度为 8-11 位的代码点在 UTF-8 中编码为:

110xxxxx  10xxxxxx

在这种情况下,0xF6 后面不是以最高两位分别设置为 1 和 0 开头的内容被错误编码。

此 UCS 代码点(246 或 0xF6)在 UTF-8 中的正确编码是 0xC3 0xB6,如下所示:

11000011  10110110

因为编码 0xF6 意味着取低 6 位并将它们插入第二个字节,而将高 2 位添加到第一个字节中。例子:

0xF6
11110110
   11    <-SPLIT->  110110
     \                 \
110xxxxx           10xxxxxx

由于 0xF6 只有 8 位,所以第一个字节中的前 3 个 x 可以设置为 0。所以你得到:

11000011  10110110

或者:

0xC3 0xB6

希望这可以帮助您正确编码使 clang 窒息的任何文件。我似乎遇到了开源这个问题。很多时候,冒犯的角色出现在评论(作者姓名)中,在这种情况下,您可以将其修改为您想要的任何内容。有时您没有修改源代码的奢侈,在这种情况下,您应该修复编码并将补丁发送给维护者。

于 2013-02-06T18:17:38.583 回答