1

GCC 编译器提供了一个编译器选项(-fexec-charset=option),因此您可以配置 char 和字符串文字的编码,因此它将您的字符串从源字符集(默认为 UTF-8)转换为执行字符集。

所以我想知道这种从源字符集到执行字符集的转换是否会导致转义序列被它们对应的代码点替换?

例如。

cout << "hello \x60 "; // \x60 replaced by byte 0x60
cout << "hello \n"; // \n replaced by 0xA0

并且在第一个示例中,此字符\x60与编码无关,而在第二个示例中,此字符 '\n' 字节表示与编码相关,也与平台相关(它将在 Windows 中更改为 \r\n,并保持为 \n on UNIX)。

4

2 回答 2

3

尽管您显然没有完全意识到这一点,但您实际上是在询问两个完全独立的转换。

第一个是在编译器中转换转义序列。这非常简单——当它\在(例如)一个字符串中看到 a 时,它会查看下一个字符并为这两个字符生成一个单字节输出(或者,根据确切的输入,它可能是来自两个以上的输入字符,例如\001)。

在 Windows 上从\nto的转换是完全独立的——这发生在输出到流的过程中——特别是文本模式流。这种转换根本不是由编译器完成的,而是由 iostreams 库中的代码完成的。\r\n

如果你真的关心第一个,这里有一些我几年前写的代码,它和编译器做的事情大致相同(尽管有 C++ 标签,这段代码是纯 C 的):

#include <string.h>
#include <stdio.h>
#include "snip_str.h"

char *translate(char *string)
{
      char *here=string;
      size_t len=strlen(string);
      int num;
      int numlen;

      while (NULL!=(here=strchr(here,'\\')))
      {
            numlen=1;
            switch (here[1])
            {
            case '\\':
                  break;

            case 'r':
                  *here = '\r';
                  break;

            case 'n':
                  *here = '\n';
                  break;

            case 't':
                  *here = '\t';
                  break;

            case 'v':
                  *here = '\v';
                  break;

            case 'a':
                  *here = '\a';
                  break;

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
                  numlen = sscanf(here,"%o",&num);
                  *here = (char)num;
                  break;

            case 'x':
                  numlen = sscanf(here,"%x",&num);
                  *here = (char) num;
                  break;
            }
            num = here - string + numlen;
            here++;
            memmove(here,here+numlen,len-num );
      }
      return string;
}
于 2013-06-10T02:42:28.537 回答
0

在网上搜索后,我现在知道我的问题的答案。因此,我将尝试为任何想知道在 c++ 中处理转义序列的机制的人解释它。

当您在文件上编写代码时,您指定文件字符集(Windows-1252, ISO-8859-1, UTF-8, UTF-16, UTF-16BE, UTF-16LE...),它将文件中的字符映射到其对应的代码点,然后使用您指定的字符集进行编码到流要保存在硬盘上的字节数。
当您尝试编译源代码文件时,如果您没有使用-finput-charset=option编译器选项指定文件编码,编译器将假定您的文件使用UTF-8. 在这两种情况下,首先要做的C PreProcessor (CPP)就是将您的文件转换为源字符集,即 UTF-8。

CPP 完成后,字符串和字符常量再次转换为执行字符集,默认情况下它与源字符集 UTF-8匹配,但您可以使用-exec-charset=option编译器选项更改它。到目前为止,一切都很清楚,我们没有谈论转义序列,因为它们的处理方式不同。

当字符串从源字符集转换为执行字符集时,有两种转义序列的处理方式不同。第一种是octal or hexadecimal转义序列like \xA1 or \45,第二种是escape sequence that get represented using a backslash followed by a characterlike \r or \n

八进制和十六进制转义序列值独立于执行字符集,这意味着它们不会从源字符集转换为执行字符集,例如,无论当前执行字符集\xA1如何,都具有该值。 剩余的转义序列值取决于执行字符集,例如将首先映射到源字符集中的对应字符,在这种情况下,它会在然后转换为执行字符集,例如,如果用户已设置,则将在字符集中字符集然后A1
'\n'0AUTF-8-fexec-charset=UTF-16BE'\n'0A00 0A源之后执行字符集转换。

Line Feed 转义字符\n甚至取决于平台,在 Windows 操作系统中,输出库将替换\n=0A\r\n=10 0A,在 Unix 中它将保留\n=0A。请注意,这种替换发生在字符和字符串从source charsetto转换之后execution charset,否则我们会得到不同的结果。

于 2013-06-23T01:04:05.053 回答