我在C ++中有一个(生成的)文字字符串,可能包含需要使用\x
表示法转义的字符。例如:
char foo[] = "\xABEcho";
但是,g ++(版本4.1.2,如果重要)会引发错误:
test.cpp:1: error: hex escape sequence out of range
编译器似乎将Ec
字符视为前一个十六进制数字的一部分(因为它们看起来像十六进制数字)。由于四位十六进制数不适合char
,因此会引发错误。显然,对于宽字符串文字L"\xABEcho"
,第一个字符是U + ABEC,然后是L"ho"
。
在过去的几十年里,这似乎发生了变化,我从未注意到。我几乎可以肯定,旧的C编译器只会在\x
之后考虑两个十六进制数字,而不再看了。
我可以想到一个解决方法:
char foo[] = "\xAB""Echo";
但这有点难看。所以我有三个问题:
这是什么时候改变的?
为什么编译器不接受宽字符串文字的> 2位十六进制转义?
是否有比上述更难的解决方法?
答案 0 :(得分:24)
GCC仅为following the standard。 #877:“每个[...]十六进制转义序列是可以构成转义序列的最长字符序列。”
答案 1 :(得分:21)
我找到了问题的答案:
C ++一直都是这样(检查过Stroustrup第3版,之前没有任何内容)。 K& R第1版根本没有提到\x
(当时唯一可用的角色逃脱是八进制)。 K& R第2版声明:
'\xhh'
其中 hh 是一个或多个十六进制数字(0 ... 9,a ... f,A ... F)。
所以从ANSI C开始出现这种行为。
虽然编译器可能只接受> 2个字符作为宽字符串文字,但这会不必要地使语法复杂化。
确实有一个不那么尴尬的解决方法:
char foo[] = "\u00ABEcho";
\u
转义始终接受四个十六进制数字。
更新:使用\u
并不适用于所有情况,因为大多数ASCII字符(由于某种原因)不允许使用\u
指定。以下是海湾合作委员会的一个片段:
/* 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;
}
答案 2 :(得分:4)
我通过使用\ xnn指定以下char来解决这个问题。不幸的是,只要[a..f]范围内有char,就必须使用它。 恩。 &#34; \ xnneceg&#34;被&#34; \ xnn \ x65 \ x63 \ x65g&#34;
取代答案 3 :(得分:3)
我很确定C ++一直都是这样的。在任何情况下,CHAR_BIT
都可能大于8,在这种情况下'\xABE'
或'\xABEc'
可能有效。
答案 4 :(得分:-1)
这些是宽字符文字。
char foo[] = "\x00ABEcho";
可能会更好。
这是一些信息,而不是gcc,但似乎仍然适用。
此链接包含重要的一行:
在wchar_t字符串文字中指定
\xnn
等同于指定\x00nn
这也可能有所帮助。
http://www.gnu.org/s/hello/manual/libc/Extended-Char-Intro.html#Extended-Char-Intro
答案 5 :(得分:-2)
我也遇到了这个问题。我发现我可以在第二个十六进制数字的末尾添加一个空格,然后通过使用退格键跟随空格来消除空格&#39; \ b&#39;。不完全可取,但似乎有效。
&#34; Julius C \ xE6sar是frana \ xE7 \ bais&#34;
的征服者