¿Por qué sizeof(estructura) no es igual a la suma de sizeof(campos)? Análisis completo

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Cómo es posible? Introducción a la paradoja de sizeof

\n\n

Imagine: crea una estructura simple en C++ con dos campos — char (1 byte) y int (4 bytes). Lógicamente, se podría suponer que su tamaño será de 5 bytes. Escribe el código, llama a sizeof y... obtiene 8 bytes. «¡Es una locura!» — piensa. «¿El compilador se ha vuelto loco?»

\n\n

Esta pregunta es una de las más populares en Stack Overflow (más de 200 000 visitas). Y no se trata de un error del compilador. Se trata de cómo el procesador y la memoria RAM realmente funcionan a bajo nivel. En este artículo, analizaremos la alineación de estructuras en C++, el concepto de padding (relleno), y aprenderemos a predecir el tamaño real de las estructuras. Y lo más importante: aprenderemos a controlarlo cuando sea realmente necesario.

\n\n

¿Por qué 1 + 4 ≠ 5? La física del proceso

\n\n

Los procesadores modernos no leen la memoria byte por byte. Trabajan con «palabras» — bloques de 4, 8 o 16 bytes (dependiendo de la arquitectura). Si un número entero de 4 bytes (int) está ubicado en una dirección que no es múltiplo de 4, el procesador tendrá que hacer dos accesos a memoria en lugar de uno para leer ese número, y luego «ensamblarlo» a partir de dos partes. Esto es catastróficamente lento.

\n\n

Para evitar esto, el compilador inserta bytes «vacíos» (padding) entre los campos de la estructura. Alinea cada campo en una dirección que sea múltiplo de su tamaño. Esto se llama alineación natural (natural alignment).

\n\n
// Ejemplo simple que sorprende a todos\n#include <iostream>\n\nstruct Example {\n    char c;   // 1 byte\n    int  i;   // 4 bytes\n};\n\nint main() {\n    std::cout << "Tamaño de char: " << sizeof(char) << std::endl;    // 1\n    std::cout << "Tamaño de int: "  << sizeof(int)  << std::endl;    // 4\n    std::cout << "Tamaño de struct: " << sizeof(Example) << std::endl; // 8 (!)\n    return 0;\n}
\n\n

¿Cómo se ve esto en memoria? c ocupa el byte 0. Los bytes 1, 2, 3 son padding. Y i comienza en el byte 4. Total: 1 (c) + 3 (vacío) + 4 (i) = 8 bytes.

\n\n

Reglas de alineación: cómo toma decisiones el compilador

\n\n

El compilador sigue reglas simples pero estrictas. Conociéndolas, podrá predecir el tamaño de una estructura sin ejecutar el programa.

\n\n
    \n
  • Regla 1: El orden de los campos se conserva. El compilador no reordena los campos en memoria (aunque algunos compiladores pueden hacerlo con optimizaciones, pero el estándar no lo garantiza).
  • \n
  • Regla 2: Cada campo se alinea en una dirección múltiplo de su tamaño. char (1 byte) puede estar en cualquier lugar. short (2 bytes) — en direcciones pares. int (4 bytes) — en direcciones múltiplos de 4. double (8 bytes) — en direcciones múltiplos de 8.
  • \n
  • Regla 3: El tamaño total de la estructura debe ser múltiplo de la alineación del campo más grande. Esto es necesario para que los arrays de estructuras funcionen correctamente. Si la variable más grande es un double (8 bytes), entonces el tamaño de la estructura será múltiplo de 8.
  • \n
\n\n

Analicemos un ejemplo más complejo:

\n\n
struct Complex {\n    char  a; // 1 byte\n    int   b; // 4 bytes\n    short c; // 2 bytes\n    char  d; // 1 byte\n};\n// ¿Cuál será el sizeof? Calculemos juntos.
\n\n

Análisis paso a paso:

\n
    \n
  • a (char) — byte 0.
  • \n
  • b (int) — debe estar en una dirección múltiplo de 4. La siguiente dirección de este tipo es 4. Por lo tanto, padding: bytes 1, 2, 3. Total después de b: 8 bytes (0-7).
  • \n
  • c (short) — debe estar en una dirección par. La posición actual es 8 (par). Perfecto. Total después de c: 10 bytes (0-9).
  • \n
  • d (char) — puede estar en cualquier lugar. Lo colocamos en el byte 10. Total después de d: 11 bytes (0-10).
  • \n

Blogs

Book Recommendations