Data Type Archaeology: Why Windows and Linux View Memory Differently?

Data Type Archaeology: Engineering, Memory, and Legacy

When developing cross-platform software in C or C++, developers often encounter bizarre behaviors: code that works perfectly on Linux might overflow memory or cause type errors on Windows. The reason isn’t just the OS, but architectural decisions dating back decades.


1. The Ghost of Segmented Memory: The “L” Prefix

If you’ve seen the LPWSTR type in Windows, the “L” stands for Long. But why would a pointer need to be “long”?

The Intel 8086 Era (16-bit)

In the 80s, processors used 16-bit addresses, limiting RAM access to only 64 KB. To use more memory, Intel created Segmentation. Memory was divided into blocks (segments).

The Transition to the Flat Model

With the arrival of 32-bit (and later 64-bit), segmentation died. Memory began to be viewed as a single, continuous block.


2. Data Models: LP64 vs. LLP64

Why is sizeof(long) 8 on Linux and 4 on Windows? The answer lies in the choice of Data Model during the 64-bit transition.

The Linux Model: LP64

Linux (and most Unix systems) adopted the LP64 model.

The Windows Model: LLP64

Windows adopted LLP64.

Why did Windows do this? To avoid breaking legacy code. Many Windows programmers assumed that sizeof(long) == sizeof(int). If Windows changed long to 64-bit, data structures saved in files would be corrupted when read by newer versions of the programs.


3. Proof of Concept: Testing Your Architecture

Use the script below to verify how your compiler and OS handle these types in practice.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

/**
 * PoC: Data Model Verification
 * Compile with: gcc main.c -o test (Linux)
 * or cl main.c (Windows)
 */
int main() {
    printf("=== Data Type Analysis ===\n");
    printf("Size of int:       %zu bytes\n", sizeof(int));
    printf("Size of long:      %zu bytes (Crucial difference here!)\n", sizeof(long));
    printf("Size of long long: %zu bytes\n", sizeof(long long));
    printf("Size of void*:     %zu bytes (Address bus width)\n", sizeof(void*));

    printf("\n=== Pointer Analysis ===\n");
    if (sizeof(void*) == 8) {
        printf("Architecture: 64-bit\n");
    } else {
        printf("Architecture: 32-bit\n");
    }

    return 0;
}