Menu

Cómo compilar y ejecutar un programa en C (gcc, paso a paso)

Convierte un archivo .c en un programa que se ejecuta: el comando gcc, qué hacen realmente el preprocesado, la compilación y el enlazado, las banderas que vale la pena usar desde el primer día, y cómo leer los errores cuando algo falla.

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

C es un lenguaje compilado: nada se ejecuta hasta que un compilador haya traducido tu código fuente a código máquina para tu CPU y sistema operativo específicos. Ese paso es un solo comando, pero saber qué hace convierte la mayoría de los mensajes de error de misteriosos en obvios.

Los dos comandos

Guarda esto como hola.c:

#include <stdio.h>

int main(void) {
    printf("¡Hola, C!\n");
    return 0;
}

Luego, en la misma carpeta:

gcc hola.c -o hola
./hola

El primer comando compila. El segundo ejecuta el resultado. En Windows el comando de ejecución es hola en el Símbolo del sistema o .\hola en PowerShell: no hay prefijo ./, porque Windows busca en el directorio actual de forma predeterminada y los shells de Unix deliberadamente no lo hacen.

Si omites -o hola, gcc nombra la salida a.out (o a.exe), que es la razón por la que los tutoriales más viejos terminan con ./a.out. Siempre nombra tu salida; cuesta cuatro caracteres y evita confusiones.

Aquí está el mismo programa en el editor del navegador, que hace ambos pasos por ti:

Qué hace realmente "compilar"

gcc hola.c -o hola parece un solo paso. Son cuatro, y cada uno puede fallar con su propio tipo de error.

1. Preprocesado. Antes de que se compile nada de C, el preprocesador procesa cada línea que empieza con #. #include <stdio.h> se reemplaza literalmente por el contenido de ese archivo de cabecera; las macros #define se expanden; los bloques #ifdef se conservan o se eliminan. La salida es un único archivo C grande sin ninguna línea #. Puedes verlo:

gcc -E hola.c

Eso imprime cientos de líneas: casi todo es stdio.h siendo pegado allí.

2. Compilación. El C preprocesado se analiza, se verifican sus tipos y se traduce a ensamblador para tu CPU. De aquí vienen los errores de sintaxis, los errores de tipos y las advertencias.

3. Ensamblado. El ensamblador se convierte en un archivo objeto: código máquina con marcadores donde van las llamadas a funciones de otros archivos.

gcc -c hola.c   # produce hola.o, se detiene antes del enlazado

4. Enlazado. Los archivos objeto se cosen junto con la biblioteca estándar de C, cada marcador se rellena con una dirección real, y el resultado es un ejecutable. De aquí vienen los errores de "undefined reference".

La conclusión práctica: un error de compilación apunta a una línea de tu código fuente, y un error de enlazado no lo hace, porque el enlazado ocurre después de que cada línea ya fue aceptada.

Banderas que vale la pena usar desde el primer día

El simple gcc archivo.c -o prog acepta en silencio mucho código peligroso. Cuatro banderas cambian eso.

gcc -std=c17 -Wall -Wextra -g hola.c -o hola
  • -Wall habilita las advertencias comunes. A pesar del nombre no son "todas" las advertencias: es el conjunto sensato.
  • -Wextra agrega más, incluyendo parámetros sin usar y algunos errores de comparación.
  • -std=c17 fija el estándar del lenguaje para que tu código signifique lo mismo en todas las máquinas. Usa -std=c99 si estás siguiendo material más antiguo.
  • -g conserva la información de depuración, para que gdb o lldb puedan mostrarte tus líneas de código reales cuando algo falla.

Dos más que querrás con el tiempo:

  • -O2 activa la optimización para compilaciones de producción. Déjala apagada mientras aprendes: el código optimizado es más difícil de depurar, y las advertencias a veces cambian.
  • -fsanitize=address,undefined (gcc y clang) hace que el programa aborte con un mensaje claro en el momento en que lee fuera de los límites o cae en comportamiento indefinido. Esta es la bandera más útil para aprender C.

Prueba las advertencias por ti mismo. Este programa compila y se ejecuta, pero tiene dos errores reales:

A count nunca se le da un valor, así que el programa imprime los bytes que hubiera allí. Con -Wall el compilador lo dice: 'count' is used uninitialized. Las advertencias en C casi nunca son ruido: trátalas como errores que todavía no te han golpeado.

Compilar más de un archivo

Los programas reales están repartidos en varios archivos. Pásaselos todos a gcc:

gcc -std=c17 -Wall main.c utils.c -o miprograma

O compila cada uno por separado y enlaza al final, que es lo que hacen los sistemas de construcción para que cambiar un archivo no reconstruya todo:

gcc -c main.c      # -> main.o
gcc -c utils.c     # -> utils.o
gcc main.o utils.o -o miprograma

Algunas bibliotecas necesitan una bandera de enlazado explícita. La biblioteca de matemáticas es la que todo principiante encuentra:

gcc calc.c -o calc -lm

Sin -lm, usar sqrt de math.h compila bien y luego falla al enlazar con undefined reference to sqrt: la declaración estaba en la cabecera, pero el código estaba en una biblioteca que nadie pidió.

Leer los errores

Los errores de C son escuetos pero consistentes. Tres ejemplos cubren la mayoría de lo que verás al principio.

Un punto y coma faltante se reporta en la siguiente línea, porque el compilador siguió leyendo:

hola.c:5:5: error: expected ';' before 'return'

El arreglo pertenece a la línea 4, no a la 5. Cada vez que un error apunte a una línea que se ve bien, revisa la línea anterior.

Una cabecera faltante parece un misterio sobre una función que claramente escribiste bien:

hola.c:4:5: warning: implicit declaration of function 'printf'

Eso significa que el compilador nunca vio una declaración de printf, así que olvidaste #include <stdio.h>. En C99 y posteriores esto es un error, no solo una advertencia.

Un fallo de enlazado no tiene ningún número de línea:

/usr/bin/ld: main.o: in function `main':
main.c:(.text+0x1a): undefined reference to `helper'

El compilador te creyó que helper existe en algún lado; el enlazador lo buscó y no está. O nunca escribiste la definición, o la escribiste con otro nombre, o te olvidaste de pasarle a gcc el archivo que la contiene.

Arregla siempre el primer error. Los errores de C se encadenan: una línea mala puede generar veinte mensajes, y diecinueve desaparecen cuando se arregla el primero.

Códigos de salida

return 0 desde main no es decoración. Es el estado de salida del programa, y el shell puede leerlo:

Después de ejecutar, echo $? en macOS/Linux (o echo %errorlevel% en Windows) imprime ese número. Los scripts y las herramientas de construcción lo usan para decidir si continúan. La convención es absoluta: 0 es éxito, y cualquier valor distinto de cero es un código de error que tú eliges. stdlib.h define EXIT_SUCCESS y EXIT_FAILURE si prefieres los nombres.

Desde C99, llegar al final de main sin un return se trata como return 0, pero escribirlo es más claro, y es obligatorio para cualquier otra función.

Preguntas frecuentes

¿Cómo compilo y ejecuto un programa en C?

Guarda el código como hola.c, luego ejecuta gcc hola.c -o hola para construirlo y ./hola para ejecutarlo (solo hola en Windows). Si gcc no se encuentra, primero necesitas instalar un compilador.

¿Qué hace gcc -o?

-o le pone nombre al archivo de salida. gcc hola.c -o hola produce un ejecutable llamado hola. Sin -o, gcc escribe en a.out (o a.exe en Windows), que es la razón por la que tantos tutoriales antiguos ejecutan ./a.out.

¿Qué banderas de gcc debería usar siempre?

gcc -std=c17 -Wall -Wextra -g tuarchivo.c -o tuprograma. -Wall -Wextra activan las advertencias que detectan errores reales, -std=c17 fija la versión del lenguaje y -g conserva los símbolos de depuración para que un depurador pueda mostrarte tu código fuente. Agrega -O2 cuando quieras velocidad en una compilación de producción.

¿Qué significa "undefined reference to" en C?

Es un error del enlazador: el compilador aceptó una llamada a una función, pero no se encontró ninguna definición de esa función. Las causas comunes son un error de tipeo en el nombre, olvidar compilar un segundo archivo .c, o usar una función matemática sin enlazar la biblioteca de matemáticas (-lm).

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR