Menu

Compilar C++: del código fuente a un ejecutable con g++

Cómo C++ convierte el código fuente .cpp en un ejecutable nativo: compila con g++ (o clang++/MSVC), ejecuta el binario y lee los errores del compilador cuando algo falla.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Compila y luego ejecuta

Ahora que tienes un compilador instalado, conseguir que un programa de C++ se ejecute es un ciclo de dos pasos. A diferencia de un lenguaje de scripting, donde un intérprete lee tu archivo línea por línea, C++ primero compila tu código fuente en un ejecutable nativo (un binario autónomo de código máquina) y después tú ejecutas ese binario directamente. No hay ningún intérprete entre tu programa y la CPU en tiempo de ejecución.

Esa separación es la razón por la que C++ es rápido, y también por la que un error de sintaxis te detiene en tiempo de compilación en lugar de a mitad de una ejecución. El compilador revisa todo el archivo antes de producir nada.

Puedes ejecutar cualquier ejemplo autónomo aquí mismo, en la página: el editor de abajo lo compila y lo ejecuta por ti. Pero vale la pena saber qué ocurre en tu propia máquina, porque ahí es donde viven los proyectos reales.

El ciclo de compilar y ejecutar en tu máquina

Supongamos que has guardado esto como main.cpp:

#include <iostream>
using namespace std;

int main() {
    cout << "Hello from the terminal" << endl;
    return 0;
}

Abre una terminal en la carpeta que contiene el archivo e invoca el compilador. El compilador más común es g++ (parte de GCC); clang++ funciona de forma idéntica para todo lo de aquí:

g++ main.cpp -o main

Si el código compila sin problemas, g++ no imprime nada y crea un archivo nuevo junto a tu fuente: un ejecutable llamado main (o main.exe en Windows). Ese binario es código máquina, no texto legible, y está ligado a tu sistema operativo y a tu CPU. Ahora ejecútalo:

./main
Hello from the terminal

En Windows lo ejecutarías como main.exe (o simplemente main) desde la misma terminal. El ./ en macOS y Linux le dice a la shell "el programa está aquí mismo, en esta carpeta, no en algún lugar del PATH", un paso que los principiantes olvidan y luego se preguntan por qué main dice command not found.

Qué hace -o (y a.out)

La opción -o da nombre a la salida. Si la omites, g++ igualmente compila, pero escribe el ejecutable con un nombre predeterminado: a.out en macOS/Linux, a.exe en Windows.

g++ main.cpp        # produces a.out, not main
./a.out

Esto confunde a la gente constantemente: compilan, no ven errores, ejecutan ./main y obtienen No such file or directory, porque el binario en realidad se llama a.out. Pasa siempre -o para saber exactamente qué estás ejecutando.

Compilas una vez por cada cambio en el código fuente. Después de eso, el ejecutable es independiente: puedes ejecutar ./main cien veces sin recompilar. Solo vuelves a ejecutar g++ cuando editas el archivo .cpp.

Elegir un estándar de C++

C++ tiene versiones (C++11, C++14, C++17, C++20, C++23), cada una añade características al lenguaje. El detalle: tu compilador elige un estándar predeterminado que puede ser más antiguo de lo que esperas, así que el código moderno puede no compilar sin razón aparente. Establece el estándar de forma explícita con -std:

g++ -std=c++17 main.cpp -o main
g++ -std=c++20 main.cpp -o main

Aquí tienes código que usa una característica de C++17 (structured bindings). Compila sin problemas en el editor, pero en tu máquina necesita -std=c++17 o más nuevo:

Si alguna vez ves un error como 'structured bindings' only available with '-std=c++17', la solución no está en tu código, sino en añadir la opción -std correcta. A lo largo de este curso, da por hecho C++17 o más nuevo.

Activa las advertencias

Un programa de C++ puede compilar sin problemas y aun así estar mal. El compilador, si se lo pides, señalará código sospechoso antes de que te muerda en tiempo de ejecución. Añade -Wall -Wextra:

g++ -std=c++17 -Wall -Wextra main.cpp -o main

Considera este programa. Compila sin -Wall, pero tiene un error real: leer una variable a la que nunca se le dio un valor, lo cual es comportamiento indefinido:

#include <iostream>
using namespace std;

int main() {
    int count;                 // never initialized
    cout << count << endl;     // reads garbage - undefined behavior
    return 0;
}

Con las advertencias activadas, el compilador lo marca:

warning: 'count' is used uninitialized [-Wuninitialized]

Adopta el hábito de compilar con -Wall -Wextra desde el primer día. Las advertencias son el compilador haciéndote una revisión de código gratis; ignorarlas es como sobreviven los errores sutiles. La solución aquí es simplemente int count = 0;.

Leer los errores del compilador

Cuando g++ rechaza tu código, indica el archivo, la línea y qué salió mal. Aprender a leer esos mensajes es la mitad del camino para desatascarte. Aquí está el clásico: un punto y coma que falta:

#include <iostream>
using namespace std;

int main() {
    cout << "Oops"      // no semicolon
    return 0;
}
main.cpp:5:5: error: expected ';' before 'return'
    5 |     return 0;
      |     ^~~~~~

Hay un par de cosas que notar. El error reporta la línea 5, pero el error está en la línea 4: el compilador solo se da cuenta de que falta un punto y coma cuando llega al siguiente token. Así que cuando un error apunta a una línea que se ve bien, revisa la línea anterior. main.cpp:5:5 es archivo, línea y luego columna. Corrige la única cosa que nombra y recompila; resiste la tentación de adivinar.

Los errores del compilador significan que todavía no se ejecutó nada. Son distintos de los errores en tiempo de ejecución, donde tu programa arrancó y luego se cayó. Detectar errores en tiempo de compilación, antes de que el programa siquiera se ejecute, es una de las mayores fortalezas de C++.

Un programa de comprobación

Ejecuta esto en el editor, o guárdalo como main.cpp y haz g++ -std=c++17 -Wall main.cpp -o main y luego ./main en tu propia máquina. Si aparecen las tres líneas, tu cadena de herramientas funciona de principio a fin:

Aquí aparecen tres cosas que conocerás como es debido muy pronto: una variable int, un vector (el arreglo redimensionable de C++) y cout para la salida. Por ahora basta con que el programa compile e imprima las tres líneas en orden.

Siguiente: Sintaxis de C++

Has compilado y ejecutado unos cuantos programas, pero hemos pasado de largo por la puntuación: las líneas #include, las llaves, los puntos y comas, int main() y por qué cada línea se ve como se ve. La siguiente página desglosa la sintaxis de C++ pieza por pieza, para que la estructura deje de sentirse como código repetitivo y empiece a tener sentido.

Preguntas frecuentes

¿Cómo compilo y ejecuto un programa de C++?

Guarda tu código como main.cpp, abre una terminal en esa carpeta y ejecuta g++ main.cpp -o main para generar un ejecutable. Luego, ejecútalo con ./main en macOS/Linux o main.exe en Windows. Compilas una sola vez; puedes ejecutar el binario resultante tantas veces como quieras.

¿Qué hace la opción -o en g++?

-o da nombre al archivo de salida. g++ main.cpp -o hello crea un ejecutable llamado hello. Si omites -o, g++ usa el nombre predeterminado a.out (o a.exe en Windows), por eso los principiantes a menudo terminan ejecutando un archivo que ni sabían que habían creado.

¿Cómo compilo C++ con un estándar específico como C++17 o C++20?

Pasa la opción -std: g++ -std=c++17 main.cpp -o main o -std=c++20. Sin ella, el compilador usa su propio valor predeterminado, que puede ser más antiguo de lo que esperas, así que funciones nuevas como los structured bindings o <ranges> pueden no compilar hasta que establezcas el estándar explícitamente.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR