简体   繁体   中英

Unsafe structs in C#

I wanted to try c#'s unsafe 'feature' by creating simple structs (Vector, Particle).

SITUATION

I have this 2 structs and want to inject position and velocity vectors into my Particle struct. As a test I wanted to print out position's X value, but somehow I'm getting random values.

I have the following code here

Vector

public readonly struct Vector
{
    public int X { get; }
    public int Y { get; }

    public Vector(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Particle

public unsafe struct Particle
{
    private Vector* mPosition;
    private Vector* mVelocity;

    public Particle(Vector position, Vector velocity = default)
    {
        mPosition = &position; // here is x 10
        mVelocity = &velocity;
    }

    public int GetPosX()
    {
        return mPosition->X; // but here not
    }
}

Program

public class Program
{
    private static void Main(string[] args)
    {
        var pos = new Vector(10, 5);
        var obj = new Particle(pos);

        Console.WriteLine(obj.GetPosX()); // prints random value
    }
}

PROBLEM

It prints a random value instead of 10.

class Program {
    static void Main (string [ ] args) {
        unsafe {
            Vector pos = new Vector(10, 5);
            Particle obj = new Particle(&pos);
            // &pos is at position 0xabcdef00 here.
            // obj.mPosition has a different value here. It points to a different address? Or am I misunderstanding something
            Console.WriteLine(obj.GetPosX( ));
        }
    }
}

public struct Vector {
    public int X;
    public int Y;

    public Vector (int x, int y) {
        X = x;
        Y = y;
    }
}

public unsafe struct Particle {
    private Vector* mPosition;

    public Particle (Vector *position) {
        mPosition = position; // here is x 10
    }

    public int GetPosX ( ) {
        return mPosition->X; // still 10 here
    }
}

This works for me. Please... do not ask me why it does. You will notice that I didn't change that much. Just calling Particle with *pos instead of pos. For some reason that fixes the problem. You have to wrap the code with unsafe then and change the constructor for Particle obviously.

I could speculate about why it works, but I'd rather not. Maybe the pointer changes when you pass pos as a parameter for some reason?

You could not take the ref with right value.

Create a variable like int posX = 10;

And you can take the reference with variable. You take the compile time reference and read the runtime reference.

Don't use pointers without fixed. C# stack performance ise very good. You dont need this.

Usually pointers use with linking (C/Cpp dynamic library linking etc). If you have large structs (30 bytes and greater) then you can use the ref parameter tag.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM