C++ c++;编译器是否将转义序列转换为实际字节?
GCC编译器提供了一个编译器选项(-fexec charset=option),因此您可以配置字符和字符串文本的编码,从而将字符串从源字符集(默认情况下为UTF-8)转换为执行字符集 所以我想知道是不是从源字符集到执行字符集的转换导致转义序列被相应的代码点替换了 例如C++ c++;编译器是否将转义序列转换为实际字节?,c++,character-encoding,escaping,sequence,C++,Character Encoding,Escaping,Sequence,GCC编译器提供了一个编译器选项(-fexec charset=option),因此您可以配置字符和字符串文本的编码,从而将字符串从源字符集(默认情况下为UTF-8)转换为执行字符集 所以我想知道是不是从源字符集到执行字符集的转换导致转义序列被相应的代码点替换了 例如 cout << "hello \x60 "; // \x60 replaced by byte 0x60 cout << "hello \n"; // \n replaced by 0xA0 cout虽然
cout << "hello \x60 "; // \x60 replaced by byte 0x60
cout << "hello \n"; // \n replaced by 0xA0
cout虽然您显然没有完全意识到这一点,但实际上您询问的是两个完全不同的转换
第一个是在编译器中转换转义序列。这非常简单——当它在(例如)字符串中看到一个\
时,它会查看下一个字符并为两个字符生成一个字节的输出(或者,根据具体的输入,它可能是两个以上输入字符的一个字节的输出,例如\001
)
在Windows上,从\n
到\r\n
的转换是完全独立的,在输出到流(特别是文本模式流)期间发生。这种转换根本不是由编译器本身完成的,而是由iostreams库中的代码完成的
如果你真的关心第一个问题,这里有几年前我写的代码和编译器做的大致相同(尽管C++标签,这个代码是纯C):
#包括
#包括
#包括“snip_街h”
字符*翻译(字符*字符串)
{
char*here=string;
尺寸长度=strlen(字符串);
int-num;
国际努姆兰;
while(NULL!=(此处=strchr(此处,'\\'))
{
numlen=1;
开关(此处为[1])
{
案例“\\”:
打破
案例“r”:
*此处='\r';
打破
案例“n”:
*此处='\n';
打破
案例“t”:
*此处='\t';
打破
案例“v”:
*此处='\v';
打破
案例“a”:
*此处='\a';
打破
案例“0”:
案例“1”:
案例“2”:
案例“3”:
案例“4”:
案例“5”:
案例“6”:
案例“7”:
numlen=sscanf(此处为“%o”&num);
*这里=(char)num;
打破
案例“x”:
numlen=sscanf(此处为“%x”、&num);
*这里=(char)num;
打破
}
num=here-string+numlen;
here++;
memmove(这里,这里+numlen,lennum);
}
返回字符串;
}
在网上搜索后,我现在知道了问题的答案。所以,我会尝试解释任何人,在处理C++中的逃逸顺序的机制时,
在文件上编写代码时,指定文件字符集(Windows-1252
,ISO-8859-1
,UTF-8
,UTF-16
,UTF-16BE
,UTF-16LE
)它会将文件中的字符映射到相应的代码点,然后使用您指定的字符集对其进行编码,该字符集将保存在硬盘上的字节流中。
当您尝试编译源代码文件时,如果您没有使用-finput charset=option
编译器选项指定文件编码,编译器将假定您的文件是使用UTF-8
编码的。在这两种情况下,C预处理器(CPP)
要做的第一件事就是将您的文件转换为源字符集,即UTF-8。
CPP完成后,字符串和字符常量将再次转换为执行字符集,默认情况下,它与源字符集UTF-8
匹配,但您可以使用-exec charset=option
编译器选项对其进行更改。到目前为止,一切都很清楚,我们并没有讨论逃逸序列,因为它们的处理方式不同
当字符串从源字符集转换为执行字符集时,有两种转义序列,每种转义序列的处理方式都不同。第一种类型是八进制或十六进制转义序列,如\xA1或\45
,第二种类型是转义序列,使用反斜杠后跟字符表示,如\r或\n
八进制和十六进制转义序列值独立于执行字符集,这意味着它们不会从源字符集转换为执行字符集,例如\xA1
具有值A1
,而不考虑当前的执行字符集。
其余的转义序列值取决于执行字符集,例如'\n'
将首先映射到源字符集中的对应字符。在这种情况下,它在UTF-8
中为0A
,然后转换为执行字符集,因此,例如,如果用户设置了-fexec charset=UTF-16BE
,则'\n'
将是源字符集中的0A
,然后在源到执行字符集转换后000a
换行符转义符\n
甚至依赖于平台,在windows操作系统中,输出库将\n=0A
替换为\r\n=10 0A
,在Unix中它将保持\n=0A
。请注意,此替换发生在从源字符集
到执行字符集
的字符和字符串转换之后,否则我们将得到不同的结果
#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;
}