簡體   English   中英

c ++編譯器如何將轉義序列轉換為實際字節?

[英]how does c++ compiler convert escape sequence to actual bytes?

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'字節表示依賴於編碼,並且還依賴於平台(它將在Windows中更改為\\ r \\ n,並保留\\ n在UNIX上)。

雖然你顯然沒有意識到這一點,但你真的要問兩個完全獨立的轉換。

第一個是在編譯器中轉換轉義序列。 這非常簡單 - 當它在(例如)字符串中看到\\時,它會查看下一個字符並為兩個字符生成單個字節的輸出(或者,根據確切的輸入,它可能是輸出的一個字節來自兩個以上的輸入字符,例如\\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;
}

在網上搜索后,我現在知道了我的問題的答案。 因此,我將嘗試為那些想知道在c ++中處理轉義序列的機制的人解釋它。

當您在文件上編寫代碼時,您指定了文件字符集( Windows-1252ISO-8859-1UTF-8UTF-16UTF-16BEUTF-16LE ......),它們將映射您的文件內的字符將文件發送到其對應的代碼點,然后使用您指定的字符集對要保存在硬盤驅動器上的字節流進行編碼。
當您嘗試編譯源代碼文件時,如果未使用-finput-charset=option編譯器選項指定文件編碼是什么,編譯器將假定您的文件使用UTF-8編碼。 在這兩種情況下, C PreProcessor (CPP)將做的第一件事是將您的文件轉換為源字符集 ,即UTF-8。

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'將首先映射到源字符集中的對應字符,在這種情況下,它在UTF-80A ,然后轉換為執行字符集 ,例如,如果用戶設置-fexec-charset=UTF-16BE然后'\\n'將在源字符集中為0A ,然后在源到執行字符集轉換后為00 0A

換行符轉義字符\\n甚至是平台相關的,在Windows操作系統中,輸出庫將用\\r\\n=10 0A替換\\n=0A \\r\\n=10 0A ,在Unix中它將保持\\n=0A 請注意,此替換發生在字符串和字符串從source charset轉換為execution charset ,否則我們將得到不同的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM