FREE LESSON · Machine code & execution · 6 OF 8

Bytes, addresses, and object layout

Bytes, addresses, and object layout: Decode endianness and alignment without confusing them with pointer validity.

Prerequisites: Hexadecimal, arrays, and byte-addressed memory.

Learning objectives

  • Translate an integer into little-endian and big-endian bytes.
  • Calculate offsets in an explicitly specified structure layout.
  • Distinguish a numeric address from a valid object access.

An address selects a byte, not a complete value

In a byte-addressed machine, consecutive addresses identify consecutive bytes. A multi-byte value occupies several addresses, and endianness specifies how the significance of those bytes maps to increasing addresses. The 32-bit value 0x12345678 occupies bytes 78 56 34 12 in little-endian order and 12 34 56 78 in big-endian order.

Endianness does not reverse the order of elements in an array. It changes the byte representation within each multi-byte element. A network or file format should specify byte order explicitly so that readers do not accidentally inherit the host machine’s layout.

value = 0x12345678
little = value.to_bytes(4, 'little')
big = value.to_bytes(4, 'big')
assert little.hex() == '78563412'
assert big.hex() == '12345678'
assert int.from_bytes(little, 'little') == value

Alignment can introduce gaps

Suppose a particular ABI gives a one-byte character alignment one, a four-byte integer alignment four, and a two-byte integer alignment two. Lay out fields in this order: character tag, four-byte count, two-byte code. The tag begins at offset zero. Three padding bytes place count at offset four. Count occupies offsets four through seven, and code occupies eight and nine. If the structure requires alignment four, two trailing padding bytes make its size twelve.

An array of these structures advances twelve bytes between elements. The next count is therefore at base+12+4, not base+10+4. This is an example with declared layout rules, not a universal rule for every language or compiler. Packed layouts may remove gaps while creating unaligned accesses or different code-generation costs.

A pointer carries obligations beyond arithmetic

A machine address is an integer-like location identifier, but a source-language pointer also participates in rules about object lifetime, bounds, alignment, and valid access types. An address that happens to be mapped does not automatically make a read legal in the language. A pointer to a freed object remains invalid even if the allocator has not yet reused the bytes.

Similarly, copying raw structure bytes can expose padding, depend on ABI choices, and fail across machines. Serialization should encode fields according to an explicit format rather than assume in-memory representation is portable. Some languages provide safe byte-conversion routines; low-level code must also consider initialization and aliasing rules.

When debugging, separate three questions: which bytes exist at the address, how the machine instruction interprets them, and whether the source program is permitted to perform that access. Confusing these layers can turn a correct-looking hexadecimal dump into an incorrect conclusion about program behavior.

Primary reading

Practice problem

Under the stated alignment rules, lay out a structure containing a two-byte code, a one-byte tag, and a four-byte count, in that order. Find offsets, total size, and the address of count in array element three when the array base is 1000 and indexing starts at zero. Encode count=0x01020304 as four little-endian bytes.

Worked solution

The two-byte code starts at offset zero and occupies bytes zero and one. The one-byte tag starts at offset two. One padding byte at offset three aligns the four-byte count to offset four. Count occupies bytes four through seven. The maximum alignment is four, and the total size eight is already a multiple of four, so no trailing padding is needed. Array element three begins at 1000+3×8=1024, and its count begins at 1028. The value 0x01020304 is stored as bytes 04 03 02 01 in little-endian order. These answers depend on the supplied ABI rules and field order; changing either can change the layout without changing the abstract meaning of the fields.

Check your understanding

What does little-endian order determine?

  • The order in which array elements are visited.
  • The least significant byte appears at the lowest address of a multi-byte value.
  • Every pointer is one byte wide.
  • Structures have no padding.
Explanation

Endianness describes byte significance within a value.

Why is a raw structure dump a fragile portable file format?

  • Bytes cannot be written to files.
  • Padding, field representation, and byte order can depend on the ABI.
  • Every structure has exactly the same layout.
  • Files cannot contain integers.
Explanation

A portable format needs explicit representation rules rather than implicit host layout.

Primary reading

Open the study and save your work →