Get the address of an array

pub static mut start: [core::ffi::c_char; 0usize];
pub static mut end: [core::ffi::c_char; 0usize];

How Do I get the Address of the variable "start and end"?

If you’re trying to do the assembly trick where you define three symbols, in order:

  • start: Just a label
  • data: Some data, often a string
  • end: Just another label

and then do end - start to calculate the length of data, that won’t work. Statics in Rust do not have a defined order in the binary.

If your data is a str or [T], the corresponding length functions are const, so you can define a static LENGTH: usize = DATA.len();

9 Likes
pub static mut start: [core::ffi::c_char; 0usize];
pub static mut end: [core::ffi::c_char; 0usize];

How Do I get the Address of the variable "start and end"?

I suspect that you’re going down a path that doesn’t go anywhere useful, but your question has a straightforward answer:

pub static mut START: [core::ffi::c_char; 0usize] =[];
pub static mut END: [core::ffi::c_char; 0usize] =[];

fn main() {
    dbg!(&raw const START);
    dbg!(&raw const END);
}
5 Likes

There's also .as_slice().as_ptr() for arrays in general, but don't use that for static mut, as the temporary reference has a huge risk of undefined behavior due to breaking Rusts aliasing rules.

That's sort of problem is why static mut is strongly discouraged now in favor of using plain static with some interior mutability like at least UnsafeCell (though you should definitely use something nicer if you can) and why &raw was added to get a pointer without going through a reference.

6 Likes

There's no point in the statics being mut if they're zero length.

This post is definitely an XY problem.

16 Likes

I am not sure what are you going to do.
Using global variable is not a good choice in most case.


Here are code to get address of start.

pub static mut start: [u8; 0usize] = [];
pub static mut end: [u8; 0usize] = [];

fn main() {
    unsafe{
        let p1 = &start as *const u8;
        let p2 = start.as_slice().as_ptr();
        println!("address={:p}, {:p}",p1, p2);
    }
}

The other posts above tell you how to get the address, but the address won't be predictable like you're expecting.

Also, the compiler may notice that your statics are ZSTs, and therefore not assign them real memory. It could decide that any reference/pointer to them will be 0x01[1] and that would be a perfectly valid optimization for the compiler[2].

Besides, what do you actually want to do? I talked to you about the XY problem before, and I'll put my response from last time into this context:

  • You want to do X (unknown to anyone except you, because you didn't tell anyone)
  • You think you can get to X by doing Y (something with the addresses of start and end)
  • You don't know how to do Y, but URLO explains it.
  • Y clearly is not going to do anything useful, so that gets repeatedly brought up (quinedot even mentions the XY problem).

Please explain what this is supposed to do. What is your X here? What are the addresses of start and end supposed to help you do?


  1. references must not be null, and the reference and the pointer must be equal ↩︎

  2. even if it wouldn't do it in practice ↩︎

4 Likes

I thought I'd cover this too; a common trick to get this to work again is to assign linker sections explicitly and depend on linker specific behavior. Quite hacky, of course, but you can do some really neat tricks with it.

1 Like

If you want to measure size of an object file that includes binary data, you don't need to bother with that — Rust has include_bytes!(path).

There are two easy way to get its address:

fn main() {
    let addr = [0u8; 20];
    println!("addr: {:?}", addr.as_ptr());
    println!("addr: {:?}", std::ptr::addr_of!(addr));
}