Dereferecing integer references

I am new to rust. Learning by coding simple programs. Wrote this simple program:

#[allow(non_camel_case_types)]

fn type_of(_: &T) {
println!("{}", std::any::type_name::())
}

fn main() {
let x = 7;
let y = &x;
let z = &y;

type_of(&x);
type_of(&y);
type_of(&z);

println!("1> x = {}, y = {}, z = {}", x, y, z);
println!("2> x = {}, *y = {},**z = {}", x, *y, **z);
println!("3> x*y = {}", x*y);
// println!("3> y*z = {}", y*z);

}

➜ src git:(main) ✗ cargo check
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
➜ src git:(main) ✗ cargo run
Compiling bits v0.1.0 (/Users/ashokchippa/rust-sandbox/bits)
Finished dev [unoptimized + debuginfo] target(s) in 0.78s
Running /Users/ashokchippa/rust-sandbox/bits/target/debug/bits
i32
&i32
&&i32
1> x = 7, y = 7, z = 7
2> x = 7, y = 7,**z = 7
3> x
y = 49
➜ src git:(main) ✗

I'm confused here. Why does rust think 'y' that references x (should be a pointer) has the value same as 'x'? If I take the comment on the last line, I get the following:

➜ src git:(main) ✗ cargo run
Compiling bits v0.1.0 (/Users/ashokchippa/rust-sandbox/bits)
error[E0277]: cannot multiply &{integer} by &&{integer}
--> src/main.rs:19:30
|
19 | println!("3> yz = {}", yz);
| ^ no implementation for &{integer} * &&{integer}
|
= help: the trait Mul<&&{integer}> is not implemented for &{integer}

For more information about this error, try rustc --explain E0277.
error: could not compile bits due to previous error

which makes sense. So am I to understand that {integer} * &{integer} has an implementation that treats &{integer} the same as *&{integer}? Confusing... Thought this was real basic. What am I missing? :frowning:

Yes, if you look at the documentation for i32 you can see that there are implementations for all the combinations of references and owned values. This allows i32 to be used in generic code that is written to also work with types that are not Copy, where you are forced to call by reference (or needlessly clone your data).

Would you mind formatting your code with triple backticks? It's a bit hard to read. All you have to do is put ``` above and below, like so:

```
fn main() {
    println!("this will be formatted as code");
}
```
3 Likes

References are more "transparent" then pointers when it comes to things like field accesses, method resolution, and trait implementations (including displaying, multiplication, et cetra).

If you want to deal with pointers, or treat addresses as integers, you'll have to use raw pointer types like *const i32 and perhaps cast the raw pointers to integers. (n.b. the exact semantics of casting to integers then back to pointers then to references is not yet decided.)

For example:

    // 
    println!("4> x = {}, y = {:p}, z = {:?}", x, y, z as *const _);
    println!("5> x*y = {:x}", x as usize * y as *const _ as usize);

({:p} for displaying pointers.)

In general, reading and writing through raw pointers is unsafe and doing things like pointer arithmetic on raw pointers is verbose in Rust, to encourage use of memory-safe references and to encourage thinking about the safety invariants often ignored in more casual contexts (cross-allocation pointer arithmetic, UB involving overflows, things like that).

y doesn't have the same value as x but merely looks the same when printed.

println! called with "{}" uses the Display trait to print out the values. The Display trait is implemented for references to dereference the value and call Display::fmt recursively on the pointed-to value.

2 Likes

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.