A raíz de una pregunta que nos hicieron el otro día, surgió la cuestión de cuanto ocupa realmente los tipos de variables que empleamos en programación. Así que voy a dedicar una entrada a hablar un poco del tema.
Tradicionalmente, en cualquier curso de programación suele ponerse una diapositiva explicando los tamaños en bytes de los distintos tipos de variables disponibles. Como introducción, suele ser suficiente.
Pero, evidentemente, si estamos aquí es porque la respuesta no es tan sencilla. En general, el tamaño de las variables depende la arquitectura del procesador, del sistema operativo, y del compilador que estemos empleando.
Pero, en lugar de solo hablar o soltaros un rollo teórico, lo mejor que podemos hacer es ilustrarlo y comprobarlo con ejemplos. Para ello vamos a medir realmente cuál es el tamaño de los diferentes tipos de variable en distintos casos.
Así, vamos comparar el tamaño de variables en un Atmega328p (Arduino), un ESP32, una Raspberry Pi 3 (ARM32), y un ordenador x64 con Windows 10 (MSC++ y G++) y Linux x64 (G++ en Ubuntu 20.04).
Por si alguno quiere replicar los resultados, el código empleado es muy sencillo. Así, el caso de Arduino y ESP32 emplearemos,
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.print("bool "); Serial.println(sizeof(bool));
Serial.print("char "); Serial.println(sizeof(char));
Serial.print("int "); Serial.println(sizeof(int));
Serial.print("long "); Serial.println(sizeof(long));
Serial.print("long long "); Serial.println(sizeof(long long));
Serial.print("float "); Serial.println(sizeof(float));
Serial.print("double "); Serial.println(sizeof(double));
Serial.print("long double "); Serial.println(sizeof(long double));
delay(10000);
}
Mientras que en caso Raspberry Pi y Windows / Linux en un ordenador de escritorio, emplearemos
#include <iostream>
int main()
{
std::cout << "bool " << sizeof(bool) << "\n";
std::cout << "char " << sizeof(char) << "\n";
std::cout << "int " << sizeof(int) << "\n";
std::cout << "long " << sizeof(long) << "\n";
std::cout << "long long " << sizeof(long long) << "\n";
std::cout << "float " << sizeof(float) << "\n";
std::cout << "double " << sizeof(double) << "\n";
std::cout << "long double " << sizeof(long double) << "\n";
}
Aquí tenemos los resultamos que obtenemos los tenemos en la siguiente tabla,
Tipo | atmega328p | esp32 | rpi 3 arm32 | Win x64 x64 MSC++ | Win x64 G++ | linux x64 g++ |
---|
| bool | 1 | 1 | 1 | 1 | 1 | 1 | | char | 1 | 1 | 1 | 1 | 1 | 1 | | int | 2 | 4 | 4 | 4 | 4 | 4 | | long | 4 | 4 | 4 | 4 | 4 | 8 | | long long | 8 | 8 | 8 | 8 | 8 | 8 | | float | 4 | 4 | 4 | 4 | 4 | 4 | | double | 4 | 8 | 8 | 8 | 8 | 8 | | long double | 4 | 8 | 8 | 8 | 16 | 16 |
Vemos que, en el caso del Atmega328p (Arduino) los resultados son los más similares a los que “tradicionalmente” se explica al enseñar los tamaños de las variables en C++. Así, vemos que un int en este caso son 2 bytes, long 4 bytes, y long long 8 bytes. Por otro lado, en coma flotante todos las variables son de 4 bytes. Por lo que “realmente” no existe un double.
Si nos vamos al ESP32 vemos que aquí que tanto int como long son 4 bytes. El ESP32 es un procesador de 32 bits, por lo cuál supone el mismo “esfuerzo” ejecutar operaciones con 4 bytes. Por tanto, el tipo int no son 2 bytes, si no 4 realmente. Por otro lado, aquí si existe el double de 8 bytes en coma flotante, pero no el long double.
En el caso de una Raspberry Pi, ARM32, con compilador G++, obtenemos exactamente los mismo resultados que en el ESP32.
Respecto a Windows, con compilador G++, es interesante ver que tanto int como long ocupan 4 bytes, mientras que long long es de 8 bytes. En linux, con el mismo compilador, ocurre lo contrario. Int son 4 bytes, mientras que long y long long son ambos tipos de variables de 8 bytes.
Por otro lado, en Windows con el compilador MSC++ (Visual Studio) contempla el tipo long double como variable de 8 bytes. Mientras que G++ amplia el tamaño de long double a 16 bytes, tanto en Windows con en Linux.
Como vemos, no es tan sencillo responder a cuál es el tamaño de las variables en C++ como se suele creer. En realidad, está lleno de matices y detalles, y para responder es necesario saber la arquitectura del procesador, el sistema operativo, y el compilador que se va a emplear.
¡Y eso que ni hemos hablado del tamaño de los punteros! Cosa de la que quizás hablemos algún día, pero en todo caso, será en una próxima entrada. ¡Hasta la próxima!