C tiene muy poca sintaxis que aprender: unas 32 palabras clave y un puñado de reglas de puntuación. Casi todos los programas que escribirás tienen la misma forma exterior, así que vale la pena desarmar esa forma una vez y con cuidado.
El programa completo más pequeño
Esto compila, se ejecuta y no hace nada:
Sin includes, sin salida, sin clase ni módulo de relleno. main es el punto de entrada: cuando el sistema operativo arranca tu programa, llama a main. Cuando main retorna, el programa termina, y el valor que devuelve es el estado de salida.
Agrega salida y necesitarás un include:
Directivas del preprocesador
Las líneas que empiezan con # se procesan antes de la compilación propiamente dicha, por el preprocesador. No son sentencias de C, y no llevan punto y coma.
#include <stdio.h> /* cabecera de la biblioteca estandar - angulos */
#include "myutils.h" /* tu propia cabecera - comillas, se busca primero al lado */
#define MAX 100 /* una macro - MAX se reemplaza por 100 en todo lo de abajo */
#include es un pegado literal de texto: el contenido entero del archivo nombrado se inserta en ese punto. stdio.h contiene la declaración de printf, que es como el compilador sabe qué argumentos recibe printf. Omite el include y obtendrás implicit declaration of function 'printf'.
La distinción entre ángulos y comillas es sobre dónde busca el compilador: <...> significa los directorios de inclusión del sistema, "..." significa buscar primero junto a este archivo.
La función main
int main(void) {
return 0;
}
Cuatro partes, cada una con significado:
int- el tipo de retorno de main. El valor va al sistema operativo como estado de salida, donde 0 significa éxito.main- el nombre reservado al que llama el entorno de ejecución. Todo programa de C alojado tiene exactamente uno.(void)- la lista de parámetros.voidaquí significa "no recibe argumentos". Escribirmain()en su lugar es legal pero más débil: los paréntesis vacíos en C significan "parámetros sin especificar", lo que desactiva la comprobación de argumentos.{ ... }- el cuerpo de la función.
La otra forma estándar recibe argumentos de línea de comandos:
int main(int argc, char *argv[]) { ... }
Usa int main(void) hasta que los necesites.
Sentencias y puntos y coma
Una sentencia es una sola instrucción, y termina con un punto y coma.
Cuatro sentencias, cuatro puntos y coma. El punto y coma es un terminador, no un separador: la última sentencia de un bloque también lo necesita.
Lo que no lleva punto y coma:
#include <stdio.h> /* linea del preprocesador - sin punto y coma */
int add(int a, int b) { /* encabezado de una definicion de funcion - sin punto y coma */
return a + b;
} /* llave de cierre de una funcion - sin punto y coma */
if (x > 0) {
...
} /* llave de cierre de un bloque de control - sin punto y coma */
El caso que muerde a todo el mundo es un punto y coma donde debería ir un cuerpo:
if (score > 90); /* BUG: este ; es todo el cuerpo del if */
printf("Excelente!\n"); /* siempre se ejecuta, valga lo que valga score */
Eso es C perfectamente legal. El if controla una sentencia vacía, y el printf es simplemente la siguiente línea en secuencia. -Wall avisa de ello; el compilador no te va a detener.
Bloques y llaves
Las llaves agrupan sentencias en un bloque, que cuenta como una sola sentencia allí donde se espera una sentencia.
Las llaves son opcionales cuando el cuerpo es una única sentencia, pero omitirlas es como ocurren los errores famosos: agregas una segunda línea más adelante y en silencio queda fuera del if. Usa llaves siempre.
Los bloques también crean ámbito: una variable declarada dentro de { ... } deja de existir en la llave de cierre.
Mayúsculas y espacios en blanco
C distingue entre mayúsculas y minúsculas en todas partes. total, Total y TOTAL son tres nombres distintos. Todas las palabras clave van en minúsculas, así que Int, Return y Printf son errores - y el mensaje de error para Printf es confuso, porque el compilador supone que te referías a alguna función de la que nunca ha oído hablar.
Los espacios en blanco, en cambio, son casi totalmente libres. El compilador trata cualquier sucesión de espacios, tabulaciones y saltos de línea como un único separador. Esto es válido:
int main ( void )
{
printf
( "Hola\n" ) ;
return 0 ;
}
Y esto también:
int main(void){printf("Hola\n");return 0;}
Ambos compilan de forma idéntica. Como al compilador le da igual, el formato es enteramente para las personas - y la disposición convencional (una sentencia por línea, cuatro espacios o una tabulación por nivel de anidamiento, llave de apertura en la misma línea) vale la pena seguirla porque toda base de código en C que leas usará algo parecido.
Dos sitios donde los espacios en blanco sí importan: no puedes partir una palabra clave o un identificador (in t no es int), y no puedes poner un salto de línea dentro de un literal de cadena normal.
Identificadores: reglas de nombres
Un identificador es cualquier nombre que elijas: variables, funciones, tipos. Las reglas:
- Formados por letras, dígitos y guiones bajos.
- No deben empezar con un dígito.
total2está bien,2totalno. - No pueden ser una palabra clave: nada de variables llamadas
int,fororeturn. - Las mayúsculas importan.
- Los nombres que empiezan con un guion bajo, y cualquiera con dos guiones bajos seguidos, están reservados para la implementación: no los inventes.
int score; /* bien */
int total_items; /* bien - snake_case es la convencion de C */
int _hidden; /* legal pero reservado - evitalo */
int 2fast; /* error */
int float; /* error - palabra clave */
Un programa totalmente anotado
Todo lo anterior, en un solo sitio:
Aquí el orden de lectura importa: with_tax se define antes de que main la use. C lee el archivo de arriba abajo, así que una función debe declararse antes de llamarla. Defínela antes, o escribe un prototipo de función arriba y defínela después.
Preguntas frecuentes
¿Cuál es la estructura básica de un programa en C?
Primero las directivas del preprocesador (#include <stdio.h>), luego las definiciones de funciones, una de las cuales debe ser main. Dentro de una función, las sentencias terminan con punto y coma y los bloques van entre llaves. Un programa mínimo es #include <stdio.h> más int main(void) { return 0; }.
¿Por qué es int main(void) y no simplemente main()?
int es el tipo de retorno de main: el estado de salida que el programa devuelve al sistema operativo. (void) dice explícitamente que main no recibe argumentos. Escribir main() con paréntesis vacíos es un estilo más antiguo que no le dice nada al compilador sobre los parámetros, así que comprueba menos.
¿Todas las sentencias de C necesitan punto y coma?
Toda sentencia sí, pero no toda línea. Las directivas del preprocesador (#include, #define), las definiciones de funciones y la llave de cierre de un bloque o de un if/for/while no lo llevan. Un punto y coma suelto después de if (x) es C perfectamente legal y hace en silencio que el cuerpo se ejecute siempre.
¿C distingue entre mayúsculas y minúsculas?
Sí, por completo. count, Count y COUNT son tres identificadores distintos, e Int no es la palabra clave int. Todas las palabras clave de C van en minúsculas, así que una mayúscula en Return o Printf produce un error.