Xcode 4.6(4H127),clang警告"字符串文字中的非法字符编码",用于ISO-8859-1编码的o-umlaut(0xF6)

pet*_*snd 3 c ascii utf-8 clang xcode4.6

此代码在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.
Run Code Online (Sandbox Code Playgroud)

pet*_*snd 5

因此,似乎来自最新Xcode(4.6)的clang接受UTF-8编码并抱怨上(或扩展)ASCII,因为通用字符集(UCS)代码的上限ASCII根据ISO-8859-1混入您的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 |
Run Code Online (Sandbox Code Playgroud)

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

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

110xxxxx  10xxxxxx
Run Code Online (Sandbox Code Playgroud)

在这种情况下,0xF6后跟不是以分别设置为1和0的最高两位开头的东西分别编码不正确.

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

11000011  10110110
Run Code Online (Sandbox Code Playgroud)

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

0xF6
11110110
   11    <-SPLIT->  110110
     \                 \
110xxxxx           10xxxxxx
Run Code Online (Sandbox Code Playgroud)

由于0xF6仅为8位,因此第一个字节中的前3个x可以设置为0.因此,您得到:

11000011  10110110
Run Code Online (Sandbox Code Playgroud)

要么:

0xC3 0xB6
Run Code Online (Sandbox Code Playgroud)

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

  • 澄清:没有“高位 ASCII”(或“高位 ASCII”)这样的东西。它要么是一个 ASCII 编码的字符,要么不是。0-127 范围之外的所有内容都使用 ASCII 以外的某种编码。通常,该编码是 ISO Latin-1 或 Unicode(其中代码点 0-255 是 ISO Latin-1,而 ISO Latin-1 的代码点 0-127 是 ASCII)。但是如果没有明确说明所使用的字符编码,我们只能说它是一个“非 ASCII”字符。在尝试理解字符编码问题时,这些术语区别很重要。 (5认同)