Skip to content
Search lessons, topics, tests…
Esc

    ↑ ↓ moveEnter openEsc close

    Module 1 · Value and Reference Types · Lesson 2 of 18

    The first-principles machine model

    1.1 Bits, bytes, addresses, and typed storage

    Before C# can make sense, we need a small but accurate machine model. We do not need electrical engineering, but we do need to know what the CPU and memory are doing.

    RAM can be viewed as a large sequence of addressable bytes. An address identifies a location. The CPU executes native instructions that load values from memory into registers, compute on them, and store results back.

    Conceptual hierarchy (not to scale)

    Text
    Fast / tiny                                             Slower / larger
    +-------------+    +-----------+    +-----------+    +----------------+
    | CPU         | -> | L1 cache  | -> | L2/L3     | -> | Main RAM       |
    | registers   | <- |           | <- | caches    | <- | byte-addressed |
    +-------------+    +-----------+    +-----------+    +----------------+

    A variable is best understood as a typed storage location in the language and runtime model. The type tells the compiler and runtime:

    • how to interpret the bits;
    • how much storage is needed for the value;
    • which operations are legal;
    • whether any bits are managed references that the GC must track;
    • how values are copied, compared, boxed, and passed.

    Under the hood note

    The C# language describes behavior. The CLR’s Common Type System gives a shared runtime model. The JIT maps that model to the target CPU’s registers, stack slots, instructions, and calling convention. Therefore, a source-level “local variable” might spend all its useful lifetime in a register and never occupy a stable RAM slot.

    1.2 A process and its important memory regions

    A .NET process uses virtual memory. The exact layout is OS- and runtime-dependent, but this conceptual map is useful:

    .NET process: conceptual virtual address space

    Text
    Higher addresses
    +------------------------------------------------------+
    | Thread A stack: method frames, locals, return data   |
    +------------------------------------------------------+
    | Thread B stack: method frames, locals, return data   |
    +------------------------------------------------------+
    | Native/runtime data, loader heaps, JIT code, modules |
    +------------------------------------------------------+
    | Managed heap: SOH generations, LOH, POH              |
    +------------------------------------------------------+
    | Static storage, mapped assemblies, OS/runtime areas  |
    +------------------------------------------------------+
    Lower addresses

    The order and growth directions above are conceptual, not contractual.

    Each OS thread has a stack. Managed objects are ordinarily allocated in GC-managed heap segments. A local reference can be held in a register or stack slot and point to an object in the managed heap.

    Question 1 - semantics

    When I assign, pass, or return this variable, what gets copied? The full value, or a reference to an object?

    Question 2 - storage

    Where are the bits stored in this particular context? In a CPU register, stack frame, object field, array payload, static storage, boxed object, or another runtime structure?

    Core idea

    Value type and reference type primarily answer Question 1. “Stack” and “heap” primarily answer Question 2.

    Sign in to mark lessons done and keep your place in the course.Sign in