Is there way to get raw pointer to field without dereferencing struct

I am specifically ask about new &raw const/&raw mut syntax.

I know that I can just use addr_of in std::ptr - Rust macro.

E.g. if I have struct

struct S {
  a: u32,
  b: u32,
}

how I express core::ptr::addr_of!((*s).a) using new syntax?

&raw is just a better syntax for addr_of! β€” it doesn't change what you can do with it.

addr_of!(expr) is equivalent to &raw const expr. The macro is soft-deprecated; use &raw const instead.

β€” addr_of in std::ptr - Rust

If you need to dereference you must have some sort of pointer to the struct, not just the struct. What type of pointer is it? For what purpose are you concerned about the dereference?

I was just confused why &raw const (*p).field requires unsafe.

It’s not &raw but *p that is relevant here. A dereference of a raw pointer is unsafe, and must be so even in this case because if the pointer was invalid, it could produce an out-of-bounds pointer. The addr_of! documentation (which can be understood as describing &raw too, until &raw gets proper documentation of its own) mentions this:

This means that addr_of!((*ptr).field) still requires the projection to field to be in-bounds, using the same rules as offset.

struct S {
  a: u32,
  b: u32,
}
fn main() {
    let s = S { a: 1, b: 2 };
    let sp = &raw const s;
    let ap = std::ptr::addr_of!((*sp).a);
    let bp = &raw const (*sp).b;
}
error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
 --> src/main.rs:8:33
  |
8 |     let ap = std::ptr::addr_of!((*sp).a);
  |                                 ^^^^^ dereference of raw pointer

error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
 --> src/main.rs:9:25
  |
9 |     let bp = &raw const (*sp).b;
  |                         ^^^^^ dereference of raw pointer

But dereferencing a reference (or Box, etc.) is safe, so you can use &raw in safe code; this compiles:

struct S {
  a: u32,
  b: u32,
}
fn main() {
    let s = S { a: 1, b: 2 };
    let sp = &s;
    let ap = std::ptr::addr_of!((*sp).a);
    let bp = &raw const (*sp).b;
}

(And in this case the dereference operator can be omitted, using implicit dereferencing of references, but that's beside the point.)

2 Likes

This doesn't seem to be the case. You need to "dereference the struct pointer before getting a raw pointer to its field:

  Compiling playground v0.0.1 (/playground)
error[E0609]: no field `a` on type `*const S`
 --> src/main.rs:9:36
  |
9 |     let ap = std::ptr::addr_of!(sp.a);
  |                                    ^ unknown field
  |
help: `sp` is a raw pointer; try dereferencing it
  |
9 |     let ap = std::ptr::addr_of!((*sp).a);
  |                                 ++  +

error[E0609]: no field `b` on type `*const S`
  --> src/main.rs:10:28
   |
10 |     let bp = &raw const sp.b;
   |                            ^ unknown field
   |
help: `sp` is a raw pointer; try dereferencing it
   |
10 |     let bp = &raw const (*sp).b;
   |                         ++  +

For more information about this error, try `rustc --explain E0609`.
error: could not compile `playground` (bin "playground") due to 2 previous errors

Rust Playground

Sorry, that part of my post might have been unclear; I have removed the further code sample because it wasn't really important. I was saying that, if you have a reference and not a raw pointer, then you can use a safe (and implicit) dereference. Dereferencing a raw pointer is unsafe, but creating one using &raw is not.

1 Like

Seems like the "safe" version is ptr.wrapping_offset(offset_of!(S, a)) but since you still need to uphold all the safety requirements before dereferencing and it adds a bunch of other ways to get it wrong I'm not sure why you'd want to bother.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.