在哪里可以找到MSIL字符串常量中的转义字符列表?

时间:2012-02-02 13:48:25

标签: c# .net cil

我编写了一个程序(在C#中),它读取和操作从C#程序生成的MSIL程序。我错误地认为MSIL字符串常量的语法规则与C#相同,但后来我遇到了以下情况:

这个C#声明

string s = "Do you wish to send anyway?";

被编译成(在其他MSIL语句中)此

IL_0128:  ldstr      "Do you wish to send anyway\?"

我没想到用来逃避问号的反斜杠。现在我可以将这个反斜杠作为我处理的一部分考虑在内,但主要是出于好奇,我想知道当C#编译器将C#常量字符串转换为MSIL常量字符串时,是否存在哪些字符被转义的列表。

感谢。

1 个答案:

答案 0 :(得分:13)

<强>更新

基于使用C#编译器+ ildasm.exe的实验:也许没有转义字符列表的原因是因为有这么少:精确到6.

来自ildasm生成的IL,来自Visual Studio 2010编译的C#程序

  • IL严格来说是 ASCII
  • 三个传统的空白字符被转义
    • \t:0x09 :(制表符)
    • \n:0x0A :(换行符)
    • \r:0x0D :(回车)
  • 转义了三个标点字符:
    • \":0x22 :(双引号)
    • \?:0x3F :(问号)
    • \\:0x5C :(反斜杠)
  • 文字字符串0x20 - 0x7E中只包含以下字符(不包括三个标点字符)
  • 所有其他字符,包括0x20以下的ASCII控制字符和从0x7F开始的所有字符都将转换为字节数组。或者更确切地说,任何包含除上面的92个字符和6个转义字符之外的任何字符的字符串都将转换为字节数组,其中字节是UTF-16字符串的 little-endian 字节。

示例1: ASCII以上0x7E:简单的重音é(U + 00E9)

C#:"é""\u00E9"成为(E9字节首先

ldstr      bytearray (E9 00 )

示例2: UTF-16:求和符号Σ(U + 2211)

C#:"∑""\u2211"成为(11字节首先

ldstr      bytearray (11 22 )

示例3: UTF-32:Double-struck mathematical(U + 1D538)

C#:""或UTF-16代理对"\uD835\uDD38"变为(char中的字节反转,但整数顺序为双字节字符)

ldstr      bytearray (35 D8 38 DD )

示例4:字节数组转换是针对包含非Ascii字符的整个字符串

C#:"In the last decade, the German word \"über\" has come to be used frequently in colloquial English."变为

ldstr      bytearray (49 00 6E 00 20 00 74 00 68 00 65 00 20 00 6C 00  
                      61 00 73 00 74 00 20 00 64 00 65 00 63 00 61 00  
                      64 00 65 00 2C 00 20 00 74 00 68 00 65 00 20 00  
                      47 00 65 00 72 00 6D 00 61 00 6E 00 20 00 77 00  
                      6F 00 72 00 64 00 20 00 22 00 FC 00 62 00 65 00  
                      72 00 22 00 20 00 68 00 61 00 73 00 20 00 63 00  
                      6F 00 6D 00 65 00 20 00 74 00 6F 00 20 00 62 00  
                      65 00 20 00 75 00 73 00 65 00 64 00 20 00 66 00  
                      72 00 65 00 71 00 75 00 65 00 6E 00 74 00 6C 00  
                      79 00 20 00 69 00 6E 00 20 00 63 00 6F 00 6C 00  
                      6C 00 6F 00 71 00 75 00 69 00 61 00 6C 00 20 00  
                      45 00 6E 00 67 00 6C 00 69 00 73 00 68 00 2E 00 )

直接,“你不能”(找到 MSIL 字符串转义列表),但这里有一些有用的花絮......

ECMA-335,其中包含CIL的严格定义,并未指定必须在QSTRING文字中转义哪些字符,只是指出可能使用反斜杠转义\字符。最重要的注意事项是:

  • Unicode文字显示为 octals ,而不是十六进制(即\042,而不是\u0022)。
  • 使用\字符可以将字符串分布在多行中 - 请参阅下面的

唯一明确提到的转义是标签\t,换行\n八进制数字转义。这对你来说有点烦人,因为C#没有八进制文字 - 你必须自己进行提取和转换,例如使用Convert.ToInt32([string], 8)方法。

除此之外,转义的选择对于规范中描述的“假设IL汇编程序”是“特定于实现的”。因此,您的问题正确地询问了 MSIL 的规则,这是Microsoft对CIL的严格实施。据我所知,MS没有记录他们选择的逃脱行为。至少可以向Mono人询问他们使用的内容。除此之外,可能需要自己生成列表 - 创建一个程序,为每个字符\u0000声明一个字符串文字 - 无论如何,看看编译的ldstr语句是什么。如果我先得到它,我一定会发布我的结果。

附加说明:

要正确解析* IL字符串文字(称为QSTRINGS或SQSTRINGS),您必须考虑的不仅仅是字符转义。以代码字符串连接为例(这是分区II :: 5.2的逐字记录):

  

“+”运算符可用于连接字符串文字。这样,通过在每行上使用“+”和新字符串,可以跨多行分解长字符串。另一种方法是使用“\”作为一行中的最后一个字符,在这种情况下,该字符及其后面的换行符不会输入到生成的字符串中。将忽略“\”与下一行中第一个非空白字符之间的任何空格字符(空格,换行符,回车符和制表符)。 [注意:要在QSTRING中包含双引号字符,请使用八进制转义序列。结束说明]

     

示例:以下字符串中的结果等同于“来自CIL的Hello World!”:

ldstr "Hello " + "World " + "from CIL!"

ldstr "Hello World\ 
       \040from CIL!"