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,但似乎仍然适用。

http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.pgmgd.doc/cpprog624.htm

这个链接包括重要的一行:

在wchar_tstring文字中指定\x00nn等同于指定\x00nn

这也可能有帮助。

http://www.gnu.org/s/hello/manual/libc/Extended-Char-Intro.html#Extended-Char-Intro