C ++编译器何时开始考虑string文字字符转义中的两个以上的hex数字?
我在C ++中有一个(生成的)string,可能包含需要使用\x
符号转义的字符。 例如:
char foo[] = "\xABEcho";
但是,g ++(版本4.1.2,如果它很重要)会抛出一个错误:
test.cpp:1: error: hex escape sequence out of range
编译器似乎将Ec
字符视为前面的hex数字的一部分(因为它们看起来像hex数字)。 由于四位hex数字不适合char
,因此会引发错误。 很显然,对于宽stringL"\xABEcho"
,第一个字符是U + ABEC,后面是L"ho"
。
在过去的几十年里,这似乎已经改变了,我从未注意到。 我几乎可以确定,旧的C编译器只会考虑\x
之后的两个hex数字,而不会再看。
我可以想到一个解决方法:
char foo[] = "\xAB""Echo";
但是这有点难看 所以我有三个问题:
-
这是什么时候改变的?
-
为什么编译器只接受宽string文本的> 2位hex转义符?
-
有没有比上面更尴尬的解决方法?
海湾合作委员会只是遵循标准 。 #877 :“每个hex转义序列是可以构成转义序列的最长字符序列。”
我find了我的问题的答案:
-
C ++一直是这样(检查Stroustrup第三版,没有任何更早)。 K&R第1版根本没有提到
\x
(当时唯一可用的字符是八进制)。 K&R第二版指出:'\xhh'
其中hh是一个或多个hex数字(0 … 9,a … f,A … F)。
所以看起来这个行为自从ANSI C以来一直存在。
-
虽然编译器可能只接受大于2个字符的string,但这会使语法不必要地复杂化。
-
确实有一个不太尴尬的解决方法:
char foo[] = "\u00ABEcho";
\u
转义字符总是接受四个hex数字。
更新 : \u
的使用不适用于所有情况,因为大多数ASCII字符(由于某种原因)不允许使用\u
来指定。 以下是GCC的一个片段:
/* The standard permits $, @ and ` to be specified as UCNs. We use hex escapes so that this also works with EBCDIC hosts. */ else if ((result < 0xa0 && (result != 0x24 && result != 0x40 && result != 0x60)) || (result & 0x80000000) || (result >= 0xD800 && result <= 0xDFFF)) { cpp_error (pfile, CPP_DL_ERROR, "%.*s is not a valid universal character", (int) (str - base), base); result = 1; }
我通过\ xnn指定下面的字符来解决这个问题。 不幸的是,只要[a..f]范围内有字符,就必须使用它。 恩。 “\ xnneceg”被replace为“\ xnn \ x65 \ x63 \ x65g”
我很确定C ++一直是这样的。 在任何情况下, CHAR_BIT
可能大于8,在这种情况下'\xABE'
或'\xABEc'
可能是有效的。
我也遇到了这个问题。 我发现我可以在第二个hex数字的末尾添加一个空格,然后通过使用退格符“\ b”跟随空格来消除空格。 不完全可取,但它似乎工作。
“朱利叶斯·卡斯特尔是”法兰西共和国的征服者“
这些是宽字符文字。
char foo[] = "\x00ABEcho";
可能会更好。
这里有一些信息,而不是gcc,但似乎仍然适用。
这个链接包括重要的一行:
在wchar_tstring文字中指定
\x00nn
等同于指定\x00nn
这也可能有帮助。
http://www.gnu.org/s/hello/manual/libc/Extended-Char-Intro.html#Extended-Char-Intro