Addressing and Byte Ordering


For programs objects that span multiple bytes it's necessary to establish two convetions:

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:

Rust
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:

Plaintext
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):

Plaintext
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:

Plaintext
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: Memory

Some machines use a different order:

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.