参考参数的 IL 差异
Difference in IL for ref paramters
我试图了解在 IL 级别处理按引用传递的参数和按值传递的参数的方式之间的区别。
下面是C#中的两个方法
public static void TestRef(ref int x)
{
x++;
}
public static void Test(int x)
{
x++;
}
按值传递的 IL 在下面,我知道它加载 arg,然后加载 int 常量 1 并将其添加并将其填回堆栈。
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: starg.s x
IL_0006: ret
通过引用传递的方法的 IL:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldind.i4
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stind.i4
IL_0007: ret
我不明白为什么会有两个 ldarg.0
语句。我假设 IL_0002/3 只是加载参数地址,然后加载该地址的参数值。
但是 IL_0001 呢?与 x =x+1
的左侧有关吗?
在IL_0001: ldarg.0
加载的地址将被在IL_0006: stind.i4
的存储操作消耗。
msdn 告诉我们有关 stind.i4
操作码的信息:
The stack transitional behavior, in sequential order, is:
An address is pushed onto the stack.
A value is pushed onto the stack.
The value and the address are popped from the stack; the value is stored at the address.
我试图了解在 IL 级别处理按引用传递的参数和按值传递的参数的方式之间的区别。
下面是C#中的两个方法
public static void TestRef(ref int x)
{
x++;
}
public static void Test(int x)
{
x++;
}
按值传递的 IL 在下面,我知道它加载 arg,然后加载 int 常量 1 并将其添加并将其填回堆栈。
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: starg.s x
IL_0006: ret
通过引用传递的方法的 IL:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldind.i4
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stind.i4
IL_0007: ret
我不明白为什么会有两个 ldarg.0
语句。我假设 IL_0002/3 只是加载参数地址,然后加载该地址的参数值。
但是 IL_0001 呢?与 x =x+1
的左侧有关吗?
在IL_0001: ldarg.0
加载的地址将被在IL_0006: stind.i4
的存储操作消耗。
msdn 告诉我们有关 stind.i4
操作码的信息:
The stack transitional behavior, in sequential order, is:
An address is pushed onto the stack.
A value is pushed onto the stack.
The value and the address are popped from the stack; the value is stored at the address.