c ++编译器如何将转义序列转换为实际字节?

时间:2013-06-10 01:57:19

标签: c++ character-encoding escaping sequence

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

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

Exmple。

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

并且在第一个示例中,此字符\x60是独立编码的,而在第二个示例中,此字符'\ n'字节表示依赖于编码,并且还依赖于平台(它将更改为\ r \ n在Windows中,并在UNIX上保留\ n。

2 个答案:

答案 0 :(得分:3)

虽然你显然没有意识到这一点,但你真的要问两个完全独立的转换。

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

Windows上从\n\r\n的转换完全分开 - 在输出到流时发生 - 特别是文本模式流。转换完全不是由编译器完成的,而是由iostreams库中的代码完成的。

如果你真的关心第一个,那么我在几年前编写的一些代码与编译器大致相同(尽管有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;
}

答案 1 :(得分:0)

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

当您在文件上编写代码时,您指定了文件字符集(Windows-1252ISO-8859-1UTF-8UTF-16UTF-16BE,{{1 }}})将文件中的字符映射到对应的代码点,然后使用您指定的字符集对要保存在硬盘驱动器上的字节流进行编码。
当您尝试编译源代码文件时,如果未使用UTF-16LE编译器选项指定文件编码是什么,编译器将假定您的文件使用-finput-charset=option进行编码。在这两种情况下,UTF-8将做的第一件事就是将您的文件转换为源字符集,即UTF-8。

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

当字符串从源字符集转换为执行字符集时,有两种转义序列的处理方式不同。第一种类型是-exec-charset=option转义序列,如octal or hexadecimal,第二种类型是\xA1 or \45,如escape sequence that get represented using a backslash followed by a character

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

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