什么时候C ++编译器开始考虑字符串文字字符转义中的两个以上十六进制数字?

时间:2011-04-26 01:22:09

标签: c++ string escaping literals

我在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位十六进制转义?

  • 是否有比上述更难的解决方法?

6 个答案:

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

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

此链接包含重要的一行:

  

在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;

的征服者