In Rust how does ampersand and asterisk work?

Asked

Viewed 132 times

8

I came from Java recently and I’m studying Rust. Language has a totally different paradigm than I was used to, but it caught my attention. For never having messed with C or C++, sometimes I find difficulties seemingly silly.

I was in doubt about the operators & (ampersand or e-comercial) and * (asterisk). When should I use them and how they work?

From what I understand, the operator & creates a, shall we say, reference; and * converts a reference to an unregistered type, but I’m not sure if that’s right.

let x = 10;
let y =  &x;
println!("{}", *y == x); // true

The above code works perfectly, although I don’t understand what it does, I know that y ends up becoming the type &i32 which is a reference to x who’s kind i32, I soon imagined that converting with alias would work too.

let x = 10;
let y =  x as &i32; // Error: non-primitive cast: `i32` as `&i32`
println!("{}", *y == x);

But an error happens when I try to convert. So I tried:

let x = 10;
let y =  &x;
println!("{}", y as i32 == x); // Error: cannot cast `&i32` as `i32`; casting `&i32` as `i32` is invalid

In the latter case the compiler detects the error and the helper suggests me use y in place of y as i32.

So I wanted to understand why he suggests this to me. If possible explain to me the operation of * and &.

1 answer

8


Basically you understood. The & creates a reference, then the value you will get is a pointer, ie a memory address of where the data actually is (reference is something that refers to something). Understand the reference as an address where a house is, and the house is the real object.

When you declare x with value 10. implicitly is saying that the type of this variable is a int32 (there is an inference of the type according to the value placed), so a space is reserved in memory to put a value of this type (4 bytes is reserved).

When you declare y is implicitly saying that the value is an address for something (the such operator & indicates this), then you have to reserve a space in memory to store it (the most typical sizes are 4 or 8 bytes depending on the architecture being 32 or 64 bits).

Understand the value of y is the address of where you are x, as indicated by the used expression. Each variable will have a different value, one is 10 and the other is something like #F2C8D4 (hexadecimal notation typically used in addresses) which is the memory address where the 10 is.

Note that the two types are very different. Even when it has 4 bytes it is just a coincidence, all semantics of the type are different. Under no circumstances can you confuse one thing with the other, is like comparing avocado with picanha. both are to eat but in different contexts and ways of preparing very distinct, you can not use the same.

If you try to access y In theory you should access the address contained there. But it’s almost never what you want, so the language provides automatic indirect access to the value referenced by this address. This means that if the object is in isolated context you do not need to use the *. But you can use it if you think it’s best to make it explicit. In some cases if you don’t, this will be a problem. The case used in the question is one of them.

If you try to compare y which is an address with x which is an integer, the types are incompatible and there is no way to give a suitable result, so you need to do something to make them compatible and then it depends on what you want. You may want to compare addresses and then the integer turns an address, or you may want to compare the value of the integer with the value pointed on the other side. You have to be explicit in what you want. So using the * is saying you want to take the amount pointed by y to compare with the value contained in x.

As the value pointed by y is exactly the same object x It can’t be any different.

Looking at it differently, let’s turn the operators into functions to give the result you want. First let’s make the addition that is an operator that everyone understands:

y + x
y.plus(x)
y = &x
y = AddressOf(x)
*y = x
ValueOfAddress(y) == x

I put in the Github for future reference.

The as does not work because there is no specific rule created to make the types become compatible by doing this, the only way is the operator *. They could have created this, but it could be confusing, they thought it best not to, no matter where you use it.

  • Very enlightened, so basically I was doing pointers without knowing kkk, this world of C is very fascinating indeed. Thanks for the answer I will try to understand more, in this time of the question until the answer by which I researched the as is a kind of 'cast' so it did not work. Thanks again, have a great year-end.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.