[英]The 'fixed' statement in C# and managed pointer in CIL code
In unsafe code in C#, I assigned a pointer to the managed variable of an array type:在 C# 的不安全代码中,我分配了一个指向数组类型托管变量的指针:
int[] array = new int[3];
// ...
fixed (int* ptr = array)
{
// Some code
}
Then I looked at corresponding part of the IL code:然后我查看了 IL 代码的相应部分:
.locals init ([0] int32[] 'array',
[1] int32& pinned ptr)
Since this is unsafe code, and int* ptr
is declaration of unmanaged pointer (or I think so at the moment), why in the CIL code doesn't write int32* ptr
, instead of int32& ptr
?由于这是不安全的代码,并且
int* ptr
是非托管指针的声明(或者我现在这么认为),为什么在CIL代码中不写int32* ptr
,而不是int32& ptr
?
http://www.ecma-international.org/publications/standards/Ecma-335.htm http://www.ecma-international.org/publications/standards/Ecma-335.htm
Page 334第 334 页
"1.1.5.2 Managed pointers (type &)
"1.1.5.2 托管指针(类型&)
1.2 Managed pointers (&) can point to a local variable, a method argument, a field of an object, a field of a value type, an element of an array, a static field, or the address where an element just past the end of an array would be stored (for pointer indexes into managed arrays).
1.2托管指针 (&) 可以指向局部变量、方法参数、对象的字段、值类型的字段、数组的元素、静态字段或元素刚刚结束的地址将存储一个数组(用于托管数组的指针索引)。 Managed pointers cannot be null.
托管指针不能为空。 (They shall be reported to the garbage collector, even if they do not point to managed memory)"
(它们应报告给垃圾收集器,即使它们不指向托管内存)"
Page 149第 149 页
7.1.2 pinned
7.1.2 固定
The signature encoding for pinned shall appear only in signatures that describe local variables (§15.4.1.3).
pinned 的签名编码应仅出现在描述局部变量的签名中(第 15.4.1.3 节)。 While a method with a pinned local variable is executing, the VES shall not relocate the object to which the local refers.
在执行带有固定局部变量的方法时,VES 不应重新定位局部变量所指的对象。 That is, if the implementation of the CLI uses a garbage collector that moves objects, the collector shall not move objects that are referenced by an active pinned local variable.
也就是说,如果 CLI 的实现使用移动对象的垃圾收集器,则收集器不应移动由活动固定局部变量引用的对象。 [Rationale: If unmanaged pointers are used to dereference managed objects, these objects shall be pinned.
[基本原理:如果非托管指针用于取消引用托管对象,则这些对象应被固定。 This happens, for example, when a managed object is passed to a method designed to operate with unmanaged data.
例如,当托管对象被传递给设计为使用非托管数据操作的方法时,就会发生这种情况。 end rationale]
结束理由]
I agree with Hans as to the rational behind the msil language design choice.关于 msil 语言设计选择背后的理性,我同意 Hans 的观点。
These two things are different:这两件事是不同的:
int[] arry = new int[5];
fixed (int* ptr = arry)
{
...
}
vs.对比
int* ptr = stackalloc int[5];
If you look at the IL created for the second one, you'll see this (which I think is what you're expecting):如果您查看为第二个创建的 IL,您会看到这一点(我认为这是您所期望的):
.locals init ([0] int32* ptr)
In the first version (your version), you're pointing to an instance of System.Array (a managed type).在第一个版本(您的版本)中,您指向 System.Array 的一个实例(托管类型)。 In my version (using stackalloc) you're pointing to what I think you're expecting to point to... a block of memory large enough for 5 ints.
在我的版本中(使用 stackalloc),您指向的是我认为您期望指向的内容……一块足够大的内存块可容纳 5 个整数。
ILDASM was written by a C++ programmer at Microsoft. ILDASM是由 Microsoft 的 C++ 程序员编写的。 A language where the difference between pointers and references are a big deal.
一种语言,指针和引用之间的区别很大。 A C++ reference under the hood is also a pointer, but one that's guaranteed to never be null.
引擎盖下的 C++ 引用也是一个指针,但它保证永远不会为空。 A reference is syntactically identified by &, a pointer is *.
引用在语法上由 & 标识,指针是 *。
Which is the case here;这里就是这种情况; there is a difference between the pointer and the pointed-to value.
指针和指向的值之间存在差异。 The pointed-to value may be null, but the reference to the pointer is never null.
指向的值可能为空,但对指针的引用永远不会为空。 The "array" variable is guaranteed to be present in the stack frame and its reference thus have a non-null value.
“数组”变量保证存在于堆栈帧中,因此其引用具有非空值。 Only its value might be null.
只有它的值可能为空。 Which happens when the array isn't initialized.
当数组未初始化时会发生这种情况。 This level of indirection made pointers unpopular and largely absent in the C# language.
这种间接级别使得指针在 C# 语言中不受欢迎并且基本上不存在。 And CS101.
和 CS101。
C# is a managed coded language, so there will not be any pointers. C# 是一种托管编码语言,因此不会有任何指针。 But there is a wrapper class to use the pointers.
但是有一个包装类来使用指针。 Maybe because of that, you are noticing some difference in these two.
也许正因为如此,您会注意到这两者之间存在一些差异。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.