---
date: '2026-07-05'
id: notes
modified: 2026-07-06 13:05:30 GMT-04:00
tags:
  - cs
title: unsigned semantics and data alignment
created: '2026-07-05'
published: '2026-07-05'
pageLayout: default
slug: hinterland/prep/bt/02-unsigned-alignment/notes
permalink: https://aarnphm.xyz/hinterland/prep/bt/02-unsigned-alignment/notes.md
generator:
  quartz: v4.6.0
  hostedProvider: Cloudflare
  baseUrl: aarnphm.xyz
full: https://aarnphm.xyz/llms-full.txt
---
## route

This module makes width and layout explicit.

1. Read `unsigned model` and `sign bridges`.
2. Solve `add32`, `sub32`, `mul32`, `shl32`, `shr32`, `to_unsigned`, and `to_signed`.
3. Read `alignment`.
4. Solve `align_up`, `align_down`, and `is_aligned`.
5. Skim `struct layout` before solving `struct_layout`.
6. Review [[hinterland/prep/02-unsigned-alignment/notes.fc]].

Depth: `c_promote_trap` and `reorder_fields`.

## unsigned model

An n-bit unsigned integer is a residue modulo $2^n$.

$$
x + y \quad\text{means}\quad (x + y) \bmod 2^n
$$

Examples at u32:

- `0xffffffff + 1 -> 0`
- `0 - 1 -> 0xffffffff`
- `0x10000 * 0x10000 -> 0`

Two’s complement signed values are the same residues relabeled. Add, subtract, and multiply produce the same bit patterns. Comparisons, division, right shift, widening, and overflow rules diverge.

| operation            | C unsigned      | C signed                                       | Python               |
| -------------------- | --------------- | ---------------------------------------------- | -------------------- |
| overflow             | wraps mod $2^n$ | undefined                                      | grows forever        |
| right shift negative | n/a             | implementation-defined, arithmetic in practice | arithmetic           |
| shift by width       | undefined       | undefined                                      | allowed              |
| `%` with negative    | n/a             | sign follows dividend                          | sign follows divisor |

The Python discipline:

<div class="notebook-runtime" data-notebook-runtime="notebook-runtime-15hub7x"></div>

<div class="notebook-code-cell" data-notebook-cell-frame="code-cell-1" id="code-cell-1" data-notebook-language="python">

<div class="notebook-runtime-cell" data-notebook-cell="code-cell-1" data-notebook-execution-count=""><span class="notebook-execution-prompt" data-notebook-execution-label="code-cell-1" aria-live="polite">In [ ]:</span></div>

<div class="notebook-cell-actions" data-notebook-cell-actions="code-cell-1">
<span class="notebook-language-badge notebook-language-badge-python" data-notebook-language="python" title="Python cell"><span class="notebook-language-icon" aria-hidden="true"><svg class="notebook-language-svg notebook-python-icon" viewBox="0 0 111 112" aria-hidden="true" focusable="false"><path fill="#3776ab" d="M54.918785.00091927421C50.335132.02221727 45.957846.41313697 42.106285 1.0946693 30.760069 3.0991731 28.700036 7.2947714 28.700035 15.032169v10.21875h26.8125v3.40625h-36.875c-7.792459 0-14.6157588 4.683717-16.7499998 13.59375-2.46181998 10.212966-2.57101508 16.586023 0 27.25 1.9059283 7.937852 6.4575432 13.593748 14.2499998 13.59375h9.21875v-12.25c0-8.849902 7.657144-16.656248 16.75-16.65625h26.78125c7.454951 0 13.406253-6.138164 13.40625-13.625v-25.53125c0-7.2663386-6.12998-12.7247771-13.40625-13.9374997C64.281548.32794397 59.502438-.02037903 54.918785.00091927421zM40.418785 8.2196694c2.769547 0 5.03125 2.2986456 5.03125 5.1249996-.000002 2.816336-2.261703 5.09375-5.03125 5.09375-2.779476-.000001-5.03125-2.277415-5.03125-5.09375-.000001-2.826353 2.251774-5.1249996 5.03125-5.1249996z"/><path fill="#ffd43b" d="M85.637535 28.657169v11.90625c0 9.230755-7.825895 16.999999-16.75 17h-26.78125c-7.335833 0-13.406249 6.278483-13.40625 13.625v25.531247c0 7.266344 6.318588 11.540324 13.40625 13.625004 8.487331 2.49561 16.626237 2.94663 26.78125 0 6.750155-1.95439 13.406253-5.88761 13.40625-13.625004V86.500919h-26.78125v-3.40625h40.187504c7.792461 0 10.696251-5.435408 13.406241-13.59375 2.79933-8.398886 2.68022-16.475776 0-27.25-1.92578-7.757441-5.60387-13.59375-13.406241-13.59375zm-15.0625 64.65625c2.779478.000003 5.03125 2.277417 5.03125 5.093747-.000002 2.826354-2.251775 5.125004-5.03125 5.125004-2.76955 0-5.03125-2.29865-5.03125-5.125004.000002-2.81633 2.261697-5.093747 5.03125-5.093747z"/></svg></span><span class="notebook-language-label">Python cell</span></span>
<button type="button" class="notebook-icon-button" data-notebook-run-cell="code-cell-1" aria-label="Run code-cell-1" title="Run code-cell-1"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-edit-cell="code-cell-1" aria-label="Edit code-cell-1" title="Edit code-cell-1"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="m4 16.5-.5 4 4-.5L19 8.5 15.5 5z"/><path d="m14 6.5 3.5 3.5"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-save-cell="code-cell-1" aria-label="Save code-cell-1 locally" title="Save code-cell-1 locally" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 4h11l3 3v13H5z"/><path d="M8 4v6h8V4"/><path d="M8 20v-6h8v6"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-revert-cell="code-cell-1" aria-label="Revert code-cell-1 local edit" title="Revert code-cell-1 local edit" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-vim-cell="code-cell-1" aria-label="Enable Vim mode" title="Enable Vim mode" hidden><svg class="notebook-vim-icon" viewBox="0 0 602 734" aria-hidden="true" focusable="false"><g transform="translate(2 3)"><path class="notebook-vim-icon-left" d="M0 155.5704 155-1l-.000003 728L0 572.237919z"/><path class="notebook-vim-icon-right" d="M443.060403 156.982405 600-1l-3.181208 728L442 572.219941z" transform="translate(521 363.5) scale(-1 1) translate(-521 -363.5)"/><path class="notebook-vim-icon-cross" d="M154.986294 0 558 615.189696 445.224605 728 42 114.172017z"/></g></svg></button>
<span class="notebook-local-source-status" data-notebook-local-source-status="code-cell-1" hidden></span>
</div>

<div class="notebook-source-editor" data-notebook-source-editor="code-cell-1" hidden></div>

```python shell
M32 = (1 << 32) - 1
add32 = (a + b) & M32
sub32 = (a - b) & M32
mul32 = (a * b) & M32
shl32 = (x << n) & M32
shr32 = (x & M32) >> n
```

<div class="notebook-runtime-output" data-notebook-output="code-cell-1" hidden></div>

</div>

## sign bridges

Unsigned bridge:

<div class="notebook-code-cell" data-notebook-cell-frame="code-cell-2" id="code-cell-2" data-notebook-language="python">

<div class="notebook-runtime-cell" data-notebook-cell="code-cell-2" data-notebook-execution-count=""><span class="notebook-execution-prompt" data-notebook-execution-label="code-cell-2" aria-live="polite">In [ ]:</span></div>

<div class="notebook-cell-actions" data-notebook-cell-actions="code-cell-2">
<span class="notebook-language-badge notebook-language-badge-python" data-notebook-language="python" title="Python cell"><span class="notebook-language-icon" aria-hidden="true"><svg class="notebook-language-svg notebook-python-icon" viewBox="0 0 111 112" aria-hidden="true" focusable="false"><path fill="#3776ab" d="M54.918785.00091927421C50.335132.02221727 45.957846.41313697 42.106285 1.0946693 30.760069 3.0991731 28.700036 7.2947714 28.700035 15.032169v10.21875h26.8125v3.40625h-36.875c-7.792459 0-14.6157588 4.683717-16.7499998 13.59375-2.46181998 10.212966-2.57101508 16.586023 0 27.25 1.9059283 7.937852 6.4575432 13.593748 14.2499998 13.59375h9.21875v-12.25c0-8.849902 7.657144-16.656248 16.75-16.65625h26.78125c7.454951 0 13.406253-6.138164 13.40625-13.625v-25.53125c0-7.2663386-6.12998-12.7247771-13.40625-13.9374997C64.281548.32794397 59.502438-.02037903 54.918785.00091927421zM40.418785 8.2196694c2.769547 0 5.03125 2.2986456 5.03125 5.1249996-.000002 2.816336-2.261703 5.09375-5.03125 5.09375-2.779476-.000001-5.03125-2.277415-5.03125-5.09375-.000001-2.826353 2.251774-5.1249996 5.03125-5.1249996z"/><path fill="#ffd43b" d="M85.637535 28.657169v11.90625c0 9.230755-7.825895 16.999999-16.75 17h-26.78125c-7.335833 0-13.406249 6.278483-13.40625 13.625v25.531247c0 7.266344 6.318588 11.540324 13.40625 13.625004 8.487331 2.49561 16.626237 2.94663 26.78125 0 6.750155-1.95439 13.406253-5.88761 13.40625-13.625004V86.500919h-26.78125v-3.40625h40.187504c7.792461 0 10.696251-5.435408 13.406241-13.59375 2.79933-8.398886 2.68022-16.475776 0-27.25-1.92578-7.757441-5.60387-13.59375-13.406241-13.59375zm-15.0625 64.65625c2.779478.000003 5.03125 2.277417 5.03125 5.093747-.000002 2.826354-2.251775 5.125004-5.03125 5.125004-2.76955 0-5.03125-2.29865-5.03125-5.125004.000002-2.81633 2.261697-5.093747 5.03125-5.093747z"/></svg></span><span class="notebook-language-label">Python cell</span></span>
<button type="button" class="notebook-icon-button" data-notebook-run-cell="code-cell-2" aria-label="Run code-cell-2" title="Run code-cell-2"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-edit-cell="code-cell-2" aria-label="Edit code-cell-2" title="Edit code-cell-2"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="m4 16.5-.5 4 4-.5L19 8.5 15.5 5z"/><path d="m14 6.5 3.5 3.5"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-save-cell="code-cell-2" aria-label="Save code-cell-2 locally" title="Save code-cell-2 locally" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 4h11l3 3v13H5z"/><path d="M8 4v6h8V4"/><path d="M8 20v-6h8v6"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-revert-cell="code-cell-2" aria-label="Revert code-cell-2 local edit" title="Revert code-cell-2 local edit" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-vim-cell="code-cell-2" aria-label="Enable Vim mode" title="Enable Vim mode" hidden><svg class="notebook-vim-icon" viewBox="0 0 602 734" aria-hidden="true" focusable="false"><g transform="translate(2 3)"><path class="notebook-vim-icon-left" d="M0 155.5704 155-1l-.000003 728L0 572.237919z"/><path class="notebook-vim-icon-right" d="M443.060403 156.982405 600-1l-3.181208 728L442 572.219941z" transform="translate(521 363.5) scale(-1 1) translate(-521 -363.5)"/><path class="notebook-vim-icon-cross" d="M154.986294 0 558 615.189696 445.224605 728 42 114.172017z"/></g></svg></button>
<span class="notebook-local-source-status" data-notebook-local-source-status="code-cell-2" hidden></span>
</div>

<div class="notebook-source-editor" data-notebook-source-editor="code-cell-2" hidden></div>

```python shell
def to_unsigned(x: int, bits: int) -> int:
  return x & ((1 << bits) - 1)
```

<div class="notebook-runtime-output" data-notebook-output="code-cell-2" hidden></div>

</div>

Signed bridge:

<div class="notebook-code-cell" data-notebook-cell-frame="code-cell-3" id="code-cell-3" data-notebook-language="python">

<div class="notebook-runtime-cell" data-notebook-cell="code-cell-3" data-notebook-execution-count=""><span class="notebook-execution-prompt" data-notebook-execution-label="code-cell-3" aria-live="polite">In [ ]:</span></div>

<div class="notebook-cell-actions" data-notebook-cell-actions="code-cell-3">
<span class="notebook-language-badge notebook-language-badge-python" data-notebook-language="python" title="Python cell"><span class="notebook-language-icon" aria-hidden="true"><svg class="notebook-language-svg notebook-python-icon" viewBox="0 0 111 112" aria-hidden="true" focusable="false"><path fill="#3776ab" d="M54.918785.00091927421C50.335132.02221727 45.957846.41313697 42.106285 1.0946693 30.760069 3.0991731 28.700036 7.2947714 28.700035 15.032169v10.21875h26.8125v3.40625h-36.875c-7.792459 0-14.6157588 4.683717-16.7499998 13.59375-2.46181998 10.212966-2.57101508 16.586023 0 27.25 1.9059283 7.937852 6.4575432 13.593748 14.2499998 13.59375h9.21875v-12.25c0-8.849902 7.657144-16.656248 16.75-16.65625h26.78125c7.454951 0 13.406253-6.138164 13.40625-13.625v-25.53125c0-7.2663386-6.12998-12.7247771-13.40625-13.9374997C64.281548.32794397 59.502438-.02037903 54.918785.00091927421zM40.418785 8.2196694c2.769547 0 5.03125 2.2986456 5.03125 5.1249996-.000002 2.816336-2.261703 5.09375-5.03125 5.09375-2.779476-.000001-5.03125-2.277415-5.03125-5.09375-.000001-2.826353 2.251774-5.1249996 5.03125-5.1249996z"/><path fill="#ffd43b" d="M85.637535 28.657169v11.90625c0 9.230755-7.825895 16.999999-16.75 17h-26.78125c-7.335833 0-13.406249 6.278483-13.40625 13.625v25.531247c0 7.266344 6.318588 11.540324 13.40625 13.625004 8.487331 2.49561 16.626237 2.94663 26.78125 0 6.750155-1.95439 13.406253-5.88761 13.40625-13.625004V86.500919h-26.78125v-3.40625h40.187504c7.792461 0 10.696251-5.435408 13.406241-13.59375 2.79933-8.398886 2.68022-16.475776 0-27.25-1.92578-7.757441-5.60387-13.59375-13.406241-13.59375zm-15.0625 64.65625c2.779478.000003 5.03125 2.277417 5.03125 5.093747-.000002 2.826354-2.251775 5.125004-5.03125 5.125004-2.76955 0-5.03125-2.29865-5.03125-5.125004.000002-2.81633 2.261697-5.093747 5.03125-5.093747z"/></svg></span><span class="notebook-language-label">Python cell</span></span>
<button type="button" class="notebook-icon-button" data-notebook-run-cell="code-cell-3" aria-label="Run code-cell-3" title="Run code-cell-3"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-edit-cell="code-cell-3" aria-label="Edit code-cell-3" title="Edit code-cell-3"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="m4 16.5-.5 4 4-.5L19 8.5 15.5 5z"/><path d="m14 6.5 3.5 3.5"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-save-cell="code-cell-3" aria-label="Save code-cell-3 locally" title="Save code-cell-3 locally" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 4h11l3 3v13H5z"/><path d="M8 4v6h8V4"/><path d="M8 20v-6h8v6"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-revert-cell="code-cell-3" aria-label="Revert code-cell-3 local edit" title="Revert code-cell-3 local edit" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-vim-cell="code-cell-3" aria-label="Enable Vim mode" title="Enable Vim mode" hidden><svg class="notebook-vim-icon" viewBox="0 0 602 734" aria-hidden="true" focusable="false"><g transform="translate(2 3)"><path class="notebook-vim-icon-left" d="M0 155.5704 155-1l-.000003 728L0 572.237919z"/><path class="notebook-vim-icon-right" d="M443.060403 156.982405 600-1l-3.181208 728L442 572.219941z" transform="translate(521 363.5) scale(-1 1) translate(-521 -363.5)"/><path class="notebook-vim-icon-cross" d="M154.986294 0 558 615.189696 445.224605 728 42 114.172017z"/></g></svg></button>
<span class="notebook-local-source-status" data-notebook-local-source-status="code-cell-3" hidden></span>
</div>

<div class="notebook-source-editor" data-notebook-source-editor="code-cell-3" hidden></div>

```python shell
def to_signed(u: int, bits: int) -> int:
  mask = (1 << bits) - 1
  sign = 1 << (bits - 1)
  return ((u & mask) ^ sign) - sign
```

<div class="notebook-runtime-output" data-notebook-output="code-cell-3" hidden></div>

</div>

Why the signed bridge works:

```text
u range:      0 ........ sign-1 | sign ........ 2^bits-1
xor sign:    sign ..... 2^bits-1 | 0 .......... sign-1
subtract:    0 ........ sign-1 | -sign ........ -1
```

Worked:

```text
to_signed(0xfe, 8)
0xfe ^ 0x80 = 0x7e = 126
126 - 128 = -2
```

## alignment

For power-of-two alignment `a`, `a - 1` is a mask of the low bits. Clearing those bits rounds down.

| task       | expression               |
| ---------- | ------------------------ |
| align down | `x & ~(a - 1)`           |
| align up   | `(x + a - 1) & ~(a - 1)` |
| is aligned | `(x & (a - 1)) == 0`     |

```mermaid
flowchart LR
  X["x"] --> Bias["add a - 1"]
  Bias --> Clear["clear low log2(a) bits"]
  Clear --> Result["first aligned address >= x"]
```

Worked with `a = 8`:

- `align_up(13, 8)`: `13 + 7 = 20`, clear low 3 bits, result `16`.
- `align_up(16, 8)`: `16 + 7 = 23`, clear low 3 bits, result `16`.
- `align_up(0, 8)`: result `0`.

The common bug is `x + a` instead of `x + a - 1`; it bumps already-aligned inputs.

Properties worth testing:

- result `>= x`
- result is aligned
- distance from `x` is `< a`
- applying `align_up` twice changes nothing

For non-power-of-two `a`, use division:

<div class="notebook-code-cell" data-notebook-cell-frame="code-cell-4" id="code-cell-4" data-notebook-language="python">

<div class="notebook-runtime-cell" data-notebook-cell="code-cell-4" data-notebook-execution-count=""><span class="notebook-execution-prompt" data-notebook-execution-label="code-cell-4" aria-live="polite">In [ ]:</span></div>

<div class="notebook-cell-actions" data-notebook-cell-actions="code-cell-4">
<span class="notebook-language-badge notebook-language-badge-python" data-notebook-language="python" title="Python cell"><span class="notebook-language-icon" aria-hidden="true"><svg class="notebook-language-svg notebook-python-icon" viewBox="0 0 111 112" aria-hidden="true" focusable="false"><path fill="#3776ab" d="M54.918785.00091927421C50.335132.02221727 45.957846.41313697 42.106285 1.0946693 30.760069 3.0991731 28.700036 7.2947714 28.700035 15.032169v10.21875h26.8125v3.40625h-36.875c-7.792459 0-14.6157588 4.683717-16.7499998 13.59375-2.46181998 10.212966-2.57101508 16.586023 0 27.25 1.9059283 7.937852 6.4575432 13.593748 14.2499998 13.59375h9.21875v-12.25c0-8.849902 7.657144-16.656248 16.75-16.65625h26.78125c7.454951 0 13.406253-6.138164 13.40625-13.625v-25.53125c0-7.2663386-6.12998-12.7247771-13.40625-13.9374997C64.281548.32794397 59.502438-.02037903 54.918785.00091927421zM40.418785 8.2196694c2.769547 0 5.03125 2.2986456 5.03125 5.1249996-.000002 2.816336-2.261703 5.09375-5.03125 5.09375-2.779476-.000001-5.03125-2.277415-5.03125-5.09375-.000001-2.826353 2.251774-5.1249996 5.03125-5.1249996z"/><path fill="#ffd43b" d="M85.637535 28.657169v11.90625c0 9.230755-7.825895 16.999999-16.75 17h-26.78125c-7.335833 0-13.406249 6.278483-13.40625 13.625v25.531247c0 7.266344 6.318588 11.540324 13.40625 13.625004 8.487331 2.49561 16.626237 2.94663 26.78125 0 6.750155-1.95439 13.406253-5.88761 13.40625-13.625004V86.500919h-26.78125v-3.40625h40.187504c7.792461 0 10.696251-5.435408 13.406241-13.59375 2.79933-8.398886 2.68022-16.475776 0-27.25-1.92578-7.757441-5.60387-13.59375-13.406241-13.59375zm-15.0625 64.65625c2.779478.000003 5.03125 2.277417 5.03125 5.093747-.000002 2.826354-2.251775 5.125004-5.03125 5.125004-2.76955 0-5.03125-2.29865-5.03125-5.125004.000002-2.81633 2.261697-5.093747 5.03125-5.093747z"/></svg></span><span class="notebook-language-label">Python cell</span></span>
<button type="button" class="notebook-icon-button" data-notebook-run-cell="code-cell-4" aria-label="Run code-cell-4" title="Run code-cell-4"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-edit-cell="code-cell-4" aria-label="Edit code-cell-4" title="Edit code-cell-4"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="m4 16.5-.5 4 4-.5L19 8.5 15.5 5z"/><path d="m14 6.5 3.5 3.5"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-save-cell="code-cell-4" aria-label="Save code-cell-4 locally" title="Save code-cell-4 locally" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 4h11l3 3v13H5z"/><path d="M8 4v6h8V4"/><path d="M8 20v-6h8v6"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-revert-cell="code-cell-4" aria-label="Revert code-cell-4 local edit" title="Revert code-cell-4 local edit" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-vim-cell="code-cell-4" aria-label="Enable Vim mode" title="Enable Vim mode" hidden><svg class="notebook-vim-icon" viewBox="0 0 602 734" aria-hidden="true" focusable="false"><g transform="translate(2 3)"><path class="notebook-vim-icon-left" d="M0 155.5704 155-1l-.000003 728L0 572.237919z"/><path class="notebook-vim-icon-right" d="M443.060403 156.982405 600-1l-3.181208 728L442 572.219941z" transform="translate(521 363.5) scale(-1 1) translate(-521 -363.5)"/><path class="notebook-vim-icon-cross" d="M154.986294 0 558 615.189696 445.224605 728 42 114.172017z"/></g></svg></button>
<span class="notebook-local-source-status" data-notebook-local-source-status="code-cell-4" hidden></span>
</div>

<div class="notebook-source-editor" data-notebook-source-editor="code-cell-4" hidden></div>

```python shell
((x + a - 1) // a) * a
```

<div class="notebook-runtime-output" data-notebook-output="code-cell-4" hidden></div>

</div>

## why alignment matters

Alignment is about how hardware fetches memory.

- A load inside one cache line is cheap.
- A load crossing a cache line can need two line reads.
- A load crossing a page can need two TLB translations.
- Atomics usually require natural alignment.
- C and Rust treat misaligned references as undefined behavior even on CPUs that tolerate the actual load.

The safe C idiom for unaligned wire data is `memcpy` into a local, then byte-swap if needed. Do not cast a byte pointer to `uint32_t *` and dereference it.

## struct layout

C layout algorithm:

1. Start `cursor = 0`.
2. For each member in declaration order, align `cursor` to that member’s alignment.
3. Place the member there and advance by its size.
4. Struct alignment is the max member alignment.
5. Struct size is rounded up to struct alignment.

Worked LP64:

| member    | align | offset | note                  |
| --------- | ----- | ------ | --------------------- |
| `char a`  | 1     | 0      | 3 bytes padding after |
| `int b`   | 4     | 4      | 4 bytes               |
| `short c` | 2     | 8      | 2 bytes               |

`sizeof` is 12, because 2 tail bytes keep array elements aligned.

Reordering by descending alignment shrinks many structs:

```text
char, double, char -> 24 bytes
double, char, char -> 16 bytes
```

Tail padding exists because `arr[i + 1]` must be aligned if `arr[i]` is.

## python struct

| prefix | order       | sizes    | padding |
| ------ | ----------- | -------- | ------- |
| `<`    | little      | standard | none    |
| `>`    | big         | standard | none    |
| `!`    | network big | standard | none    |
| `=`    | native      | standard | none    |
| `@`    | native      | native   | native  |

For wire data, always write `<` or `>`.

The default `@` is how weird bugs enter:

<div class="notebook-code-cell" data-notebook-cell-frame="code-cell-5" id="code-cell-5" data-notebook-language="python">

<div class="notebook-runtime-cell" data-notebook-cell="code-cell-5" data-notebook-execution-count=""><span class="notebook-execution-prompt" data-notebook-execution-label="code-cell-5" aria-live="polite">In [ ]:</span></div>

<div class="notebook-cell-actions" data-notebook-cell-actions="code-cell-5">
<span class="notebook-language-badge notebook-language-badge-python" data-notebook-language="python" title="Python cell"><span class="notebook-language-icon" aria-hidden="true"><svg class="notebook-language-svg notebook-python-icon" viewBox="0 0 111 112" aria-hidden="true" focusable="false"><path fill="#3776ab" d="M54.918785.00091927421C50.335132.02221727 45.957846.41313697 42.106285 1.0946693 30.760069 3.0991731 28.700036 7.2947714 28.700035 15.032169v10.21875h26.8125v3.40625h-36.875c-7.792459 0-14.6157588 4.683717-16.7499998 13.59375-2.46181998 10.212966-2.57101508 16.586023 0 27.25 1.9059283 7.937852 6.4575432 13.593748 14.2499998 13.59375h9.21875v-12.25c0-8.849902 7.657144-16.656248 16.75-16.65625h26.78125c7.454951 0 13.406253-6.138164 13.40625-13.625v-25.53125c0-7.2663386-6.12998-12.7247771-13.40625-13.9374997C64.281548.32794397 59.502438-.02037903 54.918785.00091927421zM40.418785 8.2196694c2.769547 0 5.03125 2.2986456 5.03125 5.1249996-.000002 2.816336-2.261703 5.09375-5.03125 5.09375-2.779476-.000001-5.03125-2.277415-5.03125-5.09375-.000001-2.826353 2.251774-5.1249996 5.03125-5.1249996z"/><path fill="#ffd43b" d="M85.637535 28.657169v11.90625c0 9.230755-7.825895 16.999999-16.75 17h-26.78125c-7.335833 0-13.406249 6.278483-13.40625 13.625v25.531247c0 7.266344 6.318588 11.540324 13.40625 13.625004 8.487331 2.49561 16.626237 2.94663 26.78125 0 6.750155-1.95439 13.406253-5.88761 13.40625-13.625004V86.500919h-26.78125v-3.40625h40.187504c7.792461 0 10.696251-5.435408 13.406241-13.59375 2.79933-8.398886 2.68022-16.475776 0-27.25-1.92578-7.757441-5.60387-13.59375-13.406241-13.59375zm-15.0625 64.65625c2.779478.000003 5.03125 2.277417 5.03125 5.093747-.000002 2.826354-2.251775 5.125004-5.03125 5.125004-2.76955 0-5.03125-2.29865-5.03125-5.125004.000002-2.81633 2.261697-5.093747 5.03125-5.093747z"/></svg></span><span class="notebook-language-label">Python cell</span></span>
<button type="button" class="notebook-icon-button" data-notebook-run-cell="code-cell-5" aria-label="Run code-cell-5" title="Run code-cell-5"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-edit-cell="code-cell-5" aria-label="Edit code-cell-5" title="Edit code-cell-5"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="m4 16.5-.5 4 4-.5L19 8.5 15.5 5z"/><path d="m14 6.5 3.5 3.5"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-save-cell="code-cell-5" aria-label="Save code-cell-5 locally" title="Save code-cell-5 locally" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 4h11l3 3v13H5z"/><path d="M8 4v6h8V4"/><path d="M8 20v-6h8v6"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-revert-cell="code-cell-5" aria-label="Revert code-cell-5 local edit" title="Revert code-cell-5 local edit" hidden><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></svg></button>
<button type="button" class="notebook-icon-button" data-notebook-vim-cell="code-cell-5" aria-label="Enable Vim mode" title="Enable Vim mode" hidden><svg class="notebook-vim-icon" viewBox="0 0 602 734" aria-hidden="true" focusable="false"><g transform="translate(2 3)"><path class="notebook-vim-icon-left" d="M0 155.5704 155-1l-.000003 728L0 572.237919z"/><path class="notebook-vim-icon-right" d="M443.060403 156.982405 600-1l-3.181208 728L442 572.219941z" transform="translate(521 363.5) scale(-1 1) translate(-521 -363.5)"/><path class="notebook-vim-icon-cross" d="M154.986294 0 558 615.189696 445.224605 728 42 114.172017z"/></g></svg></button>
<span class="notebook-local-source-status" data-notebook-local-source-status="code-cell-5" hidden></span>
</div>

<div class="notebook-source-editor" data-notebook-source-editor="code-cell-5" hidden></div>

```python shell
struct.calcsize('<BI') == 5
struct.calcsize('@BI') == 8
```

<div class="notebook-runtime-output" data-notebook-output="code-cell-5" hidden></div>

</div>

## guards

- `a` must be positive and power-of-two for mask alignment formulas.
- `x + a - 1` can wrap in C near the address-space top.
- `uint8_t * uint8_t` promotes to signed `int` in C before multiplication.
- `-1 < 1u` is false in C because `-1` converts to a huge unsigned value.
- `for (size_t i = n - 1; i >= 0; --i)` never terminates.
- Python `while x: x >>= 1` never terminates for negative `x`.

## drills

1. Compute `to_unsigned(-1, 8)`.
2. Compute `to_signed(0x80, 8)`.
3. Align 33 up and down to 16.
4. Explain why `a = 12` breaks `x & ~(a - 1)`.
5. Layout `char, int, short` on LP64.
6. Explain why `struct.calcsize("@ic")` differs from C `sizeof`.
7. State the C rule for unsigned overflow.
8. Explain why signed overflow being undefined helps optimization.

<script type="application/json" data-notebook-runtime-data>{"id":"notebook-runtime-15hub7x","sourcePath":"hinterland/prep/bt/02-unsigned-alignment/notes.md","language":"python","indexUrl":"https://cdn.jsdelivr.net/pyodide/v0.29.4/full/","cells":[{"id":"code-cell-1","source":"M32 = (1 \u003c\u003c 32) - 1\nadd32 = (a + b) \u0026 M32\nsub32 = (a - b) \u0026 M32\nmul32 = (a * b) \u0026 M32\nshl32 = (x \u003c\u003c n) \u0026 M32\nshr32 = (x \u0026 M32) \u003e\u003e n","language":"python","executionIndex":null},{"id":"code-cell-2","source":"def to_unsigned(x: int, bits: int) -\u003e int:\n  return x \u0026 ((1 \u003c\u003c bits) - 1)","language":"python","executionIndex":null},{"id":"code-cell-3","source":"def to_signed(u: int, bits: int) -\u003e int:\n  mask = (1 \u003c\u003c bits) - 1\n  sign = 1 \u003c\u003c (bits - 1)\n  return ((u \u0026 mask) ^ sign) - sign","language":"python","executionIndex":null},{"id":"code-cell-4","source":"((x + a - 1) // a) * a","language":"python","executionIndex":null},{"id":"code-cell-5","source":"struct.calcsize('\u003cBI') == 5\nstruct.calcsize('@BI') == 8","language":"python","executionIndex":null}],"toolbar":false,"debug":true,"vimMode":true}</script>

