C++
Variables, tipos de datos y operadores
Cómo se declaran variables en C++, qué tipos fundamentales existen y qué hacen los operadores básicos.
De dónde venimos
En ¿Qué es C++? escribiste un programa que solo imprimía texto fijo, y en La Standard Library y tu primer main() apareció la primera variable de verdad:
std::string nombre;
std::cin >> nombre;Ahí se coló mucha información sin explicar: por qué hay que escribir std::string antes del nombre, qué significa esa línea a nivel de memoria, y qué otros tipos existen además de std::string. Esta página cierra ese hueco. Todo lo que viene después en esta sección (control de flujo, funciones, punteros) se apoya en entender bien qué es una variable en C++.
Qué es una variable
Una variable es un espacio con nombre dentro de la memoria del programa, que guarda un valor de un tipo concreto. En C++ una variable tiene siempre tres cosas:
- Un tipo (
int,double,std::string…), decidido al escribirla y que ya no cambia. - Un nombre para referirte a ella.
- Una dirección de memoria donde vive físicamente el valor.
Ese tercer punto parece un detalle irrelevante ahora, pero es exactamente lo que vas a necesitar cuando lleguemos a punteros: un puntero no es más que una variable que guarda la dirección de otra.
C++ es de tipado estático: el tipo se fija cuando compilas, no cuando ejecutas. Si declaras int edad;, esa variable jamás podrá contener texto. El compilador lo verifica y falla antes de generar el programa, que es justamente lo que lo hace rápido en tiempo de ejecución.
#include <iostream>
#include <string>
int main() {
int edad = 30; // inicialización con =
double altura{1.75}; // inicialización con llaves (C++11 en adelante)
char inicial = 'C'; // comillas SIMPLES: un solo carácter
bool activo = true;
std::string nombre = "Camilo"; // comillas DOBLES: cadena de texto
std::cout << nombre << " (" << inicial << "), " << edad
<< " años, " << altura << " m, activo: " << activo << "\n";
return 0;
}Compílalo y ejecútalo (si no tienes claro qué hace cada parte de este comando, la página del compilador lo explica en detalle):
g++ -std=c++17 -Wall -o variables variables.cpp
./variablesCamilo (C), 30 años, 1.75 m, activo: 1Fíjate en el último dato: bool se imprime como 1 (verdadero) o 0 (falso), no como “true”/“false”. Es la primera de varias sorpresas pequeñas del lenguaje.
La bandera -Wall activa todas las advertencias comunes del compilador. Úsala siempre desde el primer día: la mayoría de los errores clásicos de C++ (variables sin inicializar, comparaciones sospechosas) aparecen ahí como aviso antes de convertirse en un bug real.
Los tipos fundamentales
Estos son los tipos que trae el lenguaje de fábrica, sin necesidad de ningún #include:
| Tipo | Guarda | Ejemplo de valor | Tamaño típico |
|---|---|---|---|
int | Números enteros con signo | -7, 0, 42 | 4 bytes |
double | Números con decimales | 3.14, -0.5 | 8 bytes |
float | Decimales de menor precisión | 3.14f | 4 bytes |
bool | Verdadero o falso | true, false | 1 byte |
char | Un solo carácter | 'A', '\n' | 1 byte |
unsigned int | Enteros sin signo (solo ≥ 0) | 0, 3000000000 | 4 bytes |
std::string no está en esta tabla a propósito: no es un tipo fundamental del lenguaje, sino una clase de la Standard Library. Por eso necesita #include <string> y lleva el prefijo std::, tal como se explicó en Namespaces y el prefijo std::.
La columna “tamaño típico” es exactamente eso: típico, no garantizado. El estándar de C++ solo fija tamaños mínimos y relaciones entre tipos; un int puede tener 2, 4 u 8 bytes según la plataforma. Si necesitas un entero de tamaño exacto (formatos de archivo, protocolos de red, registros de hardware), usa los tipos de <cstdint>: int32_t, uint8_t, int64_t. Nunca asumas sizeof(int) == 4 en código que deba ser portable.
auto: que el compilador deduzca el tipo
Desde C++11 puedes escribir auto y dejar que el compilador infiera el tipo a partir del valor inicial:
auto contador = 0; // int
auto precio = 19.99; // double
auto letra = 'x'; // charEsto no convierte a C++ en un lenguaje de tipado dinámico: el tipo sigue siendo fijo y decidido en compilación, solo que no lo escribes tú. auto brilla sobre todo con tipos largos de la Standard Library (iteradores, plantillas), donde escribir el tipo completo sería ruido puro.
Este ejemplo con auto no es representativo del uso real. En código de producción casi nadie escribe auto contador = 0; en lugar de int contador = 0; — con tipos cortos y obvios, escribir el tipo es más legible. auto se usa de verdad cuando el tipo es largo o directamente impronunciable, como std::vector<std::string>::const_iterator.
const: valores que no cambian
Anteponer const marca una variable como de solo lectura: el compilador rechaza cualquier intento de modificarla.
const double PI = 3.14159;
// PI = 3.0; // ERROR de compilación: assignment of read-only variable 'PI'Usar const no es una formalidad: le comunica tu intención al compilador y a quien lea el código, y evita modificaciones accidentales. Cobrará mucha más importancia cuando pases datos a funciones por referencia.
Operadores básicos
Aritméticos
| Operador | Qué hace | Ejemplo (a = 7, b = 2) | Resultado |
|---|---|---|---|
+ | Suma | a + b | 9 |
- | Resta | a - b | 5 |
* | Multiplicación | a * b | 14 |
/ | División | a / b | 3 (!) |
% | Resto de división | a % b | 1 |
7 / 2 da 3, no 3.5. Cuando ambos operandos son enteros, C++ hace división entera y descarta la parte decimal sin avisar (no redondea: trunca). Para obtener 3.5, al menos uno de los dos debe ser de tipo decimal: 7.0 / 2, o static_cast<double>(a) / b si trabajas con variables. static_cast<double>(a) es una conversión explícita: le pide al compilador “trata este valor como si fuera double”, justo antes de la división, así ya no son dos enteros y no se trunca. Este es probablemente el error silencioso número uno de quien empieza en C++ (y en C, y en Java…).
El operador % solo funciona con enteros, y es más útil de lo que parece: n % 2 == 0 comprueba si un número es par, y aparecerá otra vez en la página de control de flujo.
Comparación y lógicos
Los de comparación devuelven un bool: == (igual), != (distinto), <, >, <=, >=.
Los lógicos combinan condiciones: && (y), || (o), ! (no).
= asigna, == compara. Escribir if (x = 5) compila sin error en muchos casos: asigna 5 a x y la condición resulta verdadera siempre. Con -Wall el compilador te avisa; sin -Wall, no. Es un bug clásico que puede costar horas.
Incremento, decremento y asignación compuesta
++i/i++suman 1;--i/i--restan 1.+=,-=,*=,/=combinan operación y asignación:total += 5estotal = total + 5.
La diferencia entre ++i (pre-incremento: incrementa y luego devuelve el valor nuevo) e i++ (post-incremento: devuelve el valor viejo y luego incrementa) solo importa cuando usas el resultado dentro de una expresión más grande. En un bucle suelto, ambos hacen lo mismo. Por cierto, el nombre del lenguaje viene precisamente de este operador: C++ es “C incrementado en uno”.
Ejemplo completo: promedio de dos notas
Este programa junta todo lo anterior con la entrada por consola que ya viste con std::cin:
#include <iostream>
int main() {
double nota1 = 0.0;
double nota2 = 0.0;
std::cout << "Ingresa la primera nota: ";
std::cin >> nota1;
std::cout << "Ingresa la segunda nota: ";
std::cin >> nota2;
const double promedio = (nota1 + nota2) / 2.0; // 2.0, no 2, para evitar división entera
std::cout << "Promedio: " << promedio << "\n";
std::cout << "¿Aprobado? " << (promedio >= 4.0) << "\n";
return 0;
}g++ -std=c++17 -Wall -o promedio promedio.cpp
./promedioIngresa la primera nota: 5.5
Ingresa la segunda nota: 3.5
Promedio: 4.5
¿Aprobado? 1Fíjate que aquí las variables son double, así que (nota1 + nota2) / 2.0 sí produce decimales. El 2.0 está escrito así deliberadamente: aunque en este caso 2 también funcionaría (porque los operandos ya son double), acostumbrarte a escribir el punto decimal te ahorra la trampa cuando trabajes con enteros.
Una variable declarada sin valor inicial (int x;) no vale 0: contiene basura, es decir, lo que hubiera antes en esa zona de memoria. Leerla es comportamiento indefinido: el programa puede imprimir un número aleatorio, funcionar de casualidad hoy y fallar mañana. Inicializa siempre en la declaración (int x = 0;). Esta misma regla, aplicada a punteros, es la causa de los crashes más comunes de C++, y volveremos a ella en Punteros.
Siguiente paso
Ya sabes guardar y operar valores, pero el programa sigue ejecutándose siempre de arriba a abajo, línea por línea. Para que tome decisiones y repita trabajo, sigue con Control de flujo: if, for, while y switch.