Using an int pointer in rust

Hello,

I want to build a VM and have a struct

struct Code {
    capacity: u32,
    count: u32
    code: *const i32
}

Is there a better way to solve this? I need to initialise the struct with all values 0 and the pointer as NULL
I also need to set the pointer reference.
Or would you solve it with a reference?

...
code: *mut T

Are you interfacing with C or C++ code? If not, you shouldn't use unsafe.

We're missing the bigger picture, But look into Option in std::option - Rust and Defining and Instantiating Structs - The Rust Programming Language. You may be able to use a reference, an index or another kind of data structure, depending on how you intent to use it.

1 Like

thanks for your reply!
I am not interfacing with c or c++ code. I will read what you linked.

I don't understand your problem description at all.

I see you store the capacity along with the pointer, I would assume it's an owned pointer, then this struct is essentially Vec<i32> (except you use 32 bit to store the length), and you can create an empty Vec just fine.

if the pointer is not owned, you don't need the capacity field, then the struct is essentially just a slice, i.e. &[i32], and if it is "null-able", you can wrap it in Option, and Option<&[i32]> consumes the same memory as &[i32].

Sorry youre right, I should have mentioned that my problem lies in code: *const i8 which is supposed to be comparable to a pointer to an array of bytes containing OpCodes in C of the VM. I am unsure what to use. Should I instead use code: &mut i8?

I would recomment you to read an introduction to rust. You probably want Vec<i8> or &mut [i8]

without more details, it's hard to say what's the best choice. but in general, for a pointer from C, using raw pointers is fine. reference can also be used. if it's a pointer to a single i32, then &i32 can be used. if it's a pointer to the first element of an array of i32s, then you should use &[i32], not &i32.

since it's a pointer from C, you'd better not use mut references, unless you know excactly what you are doing.

dealing with C pointers requires unsafe anyway, so always be careful of UB.

thanks for your reply! the array that the pointer points to should have operations added to it and grow in size. so I should probably use vec instead. In this case it should be code: & mut vec or do you have another idea?

Since you don't give a lot of information I'll assume that you want to store something like instructions or opcodes.

Vec already has fields for length and capacity. So probably you just want

let code = Vec::<i32>::new();

or if you need a new type you can either use the Newtype pattern

struct Code(Vec<i32>)

Or a struct with a Vec field

struct Code {
  instructions: Vec<i32>,
}

They all translate basically to the same thing in the end.

You can then add methods to the struct as needed

impl Code {
  fn add_instruction(&mut self, instr: i32) -> Result<(), ()> {
    check_valid(instr)?;
    self.instructions.push(instr);
    Ok(())
  }
}

You usually don't want a &mut Vec inside another structure as that just adds problems with lifetimes and someone needs to be the owner of the data.

2 Likes

I don't really understand this part. How do you retrieve this pointer to an array of bytes? Do you want to use Code.code to index into that array? If yes, why? Wouldn't it be easier to just store the opcodes directly?

I am going to try a vec<i8> now.I wanted code to hold the address to an i8
array.

In general it doesn't work to think of solutions that you would use in C/C++ and then try to implement them in Rust, because Rust prevents data races and C/C++ do not. Rust is very different in this respect.

So it is better to take a look at the Rust book and the std library, and look for an API that does what you need. The std library has implementations that use unsafe Rust for optimal performance, but are verified to contain no data races. In some cases you'll need to use other crates as well, of course.

You can write unsafe code yourself of course, but this is a very advanced skill and it is not the same as writing C/C++ code -- it is much more difficult. So I strongly recommend that you don't try to write unsafe code until you've been using Rust for quite a while, and you may never need to do it.

6 Likes