Reputation: 59
I'm reconstructing u128
numbers passed over the internet. My idea is to break the number down into u8
s on one end of the connection, send those and rebuild the u128
on the other end.
I attempted reconstructing a u8
buffer by casting its pointer to *const u8
to *const u128
:
fn main() {
let mut b = [0u8; 16];
b[14] = 1;
let addr = &b as *const u8 as *const u128;
unsafe {
println!("{:?}", &b as *const u8);
println!("{:?}\n", b);
println!("{:?}", addr);
println!("n = {}", *addr);
}
}
To my surprise, the generated output looked like this:
0x7efe2088
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
0x7efe2088
n = 5192296858534827628530496329220096
I expected this array to contain
00000000 00000000 ... 00000001 00000000 = 256
Now I'm confused. Considering two different options as possibilities:
b[14]
as the second byte;*const u128
(which points to b[0]
) reads the allocated bytes backwards.Which one of these is correct? Is there something I don't understand about the way Rust (or computers in general) store data?
Upvotes: 3
Views: 1129
Reputation: 1455
Your confusion stems from endianness. This concept applies to computers in general, not just Rust. Some computer architectures are natively big-endian (e.g. MIPS), some are little endian (e.g. x86), and some can be both (e.g. ARM)!.
For transporting the numbers over the internet, you should choose what order you want send them (either big-endian or little endian; big-endian is the traditional choice, though little-endian systems are more common these days), and then explicitly convert when sending and receiving. This way, your program will still work even if the two computers talking have a different endianness (for example, MIPS and x86-64 are different).
As @loganfsmyth notes, Rust has built-in methods to do this conversion from a u128
to an array of u8
s (and vice-versa), these methods are:
Upvotes: 8