Addressing and Byte Ordering
For programs objects that span multiple bytes it's necessary to establish two convetions:
- what the address of the object
- how to order the bytes in memory
In virtually all machines this object is stored as a contiguous sequence of bytes, where the address is the smallest address of the byte used. This can be checked with this Rust code:
fn main() {
let x: i32 = 10;
let raw_ptr: *const i32 = &x;
unsafe {
println!("Address of x: {:p}", raw_ptr);
for i in 0..std::mem::size_of_val(&x){
let byte_ptr = (raw_ptr as *const u8).wrapping_offset(i as isize);
let byte_value = *byte_ptr;
println!("Byte {} at address {:p} contains: 0x{:x}", i, byte_ptr, byte_value);
}
}
}
It prints:
Address of x: 0x16ba96df4
Byte 0 at address 0x16ba96df4 contains: 0xa
Byte 1 at address 0x16ba96df5 contains: 0x0
Byte 2 at address 0x16ba96df6 contains: 0x0
Byte 3 at address 0x16ba96df7 contains: 0x0
Now the same program but with the number 2147483647
(which is at the higher end of what int
can represent):
Address of x: 0x16d522df4
Byte 0 at address 0x16d522df4 contains: 0xbf
Byte 1 at address 0x16d522df5 contains: 0x63
Byte 2 at address 0x16d522df6 contains: 0xff
Byte 3 at address 0x16d522df7 contains: 0x7f
We can add convert those values to binary:
Address of x: 0x16d522df4
Byte 0 at address 0x16d522df4 contains: 0xbf // 10111111
Byte 1 at address 0x16d522df5 contains: 0x63 // 1100011
Byte 2 at address 0x16d522df6 contains: 0xff // 11111111
Byte 3 at address 0x16d522df7 contains: 0x7f // 11111111
The number 2147483647
in binary is 1111111111111111110001110111111
. We can see that Byte 0 stores the least significant byte while Byte 3 stores the most significant.
Visual representation:
Some machines use a different order:
- least to most: referred to as little endian
- most to least: referred to as big endian
This byte ordering is totally irrelevant, one is not better than the other. Little endian is used almost everywhere. For application programmers the order is totally invisible, compilers will deal with that stuff. However, ordering matters when sending sending binary data over the network. A common problem is for data to be sent by a little endian machine to be read by a big endian, or vice versa. This leads to problem. Code written for networking applications must follow established conventions for byte ordering to make sure the sending machine converts its internal representation to the network standard, while the receiving machine converts the network standard to its internal representation.