Question

In the following code I build a pointer to a struct located at an arbitrary memory location:

[StructLayout(LayoutKind.Explicit)]
public struct S
{
    [FieldOffset(0)] int f0;
    [FieldOffset(4)] int f4;

    public static void Main() {
        unsafe {
            S* rawPtr = (S*)0x1234;
            rawPtr->f0 = 42;
        }
    }
}

If I change f4's type to object instead of int, I get the error Compiler Error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('type').

What are the constaints on struct S that allow building pointers on that type, at the CIL (not just C#) level?

This page on MSDN says sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, enums and pointers are allowed, as well as "user-defined struct type that contains fields of unmanaged types only", but doesn't specify what an unmanaged type is.

Was it helpful?

Solution

I could not find an easily navigable version of ECMA-335 online, but ECMA-334 paragraph 27.2 says:

An unmanaged-type is any type that isn’t a reference-type, a type-parameter, or a generic struct-type and contains no fields whose type is not an unmanaged-type. In other words, an unmanaged-type is one of the following:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.

  • Any enum-type.

  • Any pointer-type.

  • Any non-generic user-defined struct-type that contains fields of unmanaged-types only.

[Note: Constructed types and type-parameters are never unmanaged-types. end note]

The packing mode of a structure does not seem to be relevant to this distinction.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top