Una variable es un trozo de memoria con nombre que contiene un valor que tu programa puede leer y cambiar. En C dices de antemano qué clase de valor contiene, y esa elección es permanente durante toda la vida de la variable.
Declarar una variable
La forma es tipo, nombre, punto y coma:
int age;
double price;
char grade;
Cada línea reserva memoria suficiente para ese tipo de dato y le adjunta un nombre. Todavía no se ha guardado nada: el espacio existe, pero su contenido es lo que haya dejado ahí lo que se ejecutara antes.
Puedes dar un valor en el mismo momento, lo que se llama inicialización:
Fíjate en los especificadores de formato: %d para int, %f para double, %c para char. printf no inspecciona los valores que le dan: se fía de tu cadena de formato, así que un desajuste imprime disparates en lugar de dar un error.
Asignación después de la declaración
Una vez que una variable existe, la cambias con =:
En C, = es asignación, no igualdad. score = score + 10 se lee como "toma lo que hay en score, súmale 10 y vuelve a poner el resultado en score". El operador de comparación es ==, y confundirlos es un error tan común que tiene su propia sección en la página de booleanos.
El atajo score += 10 hace lo mismo con menos caracteres; los operadores de asignación compuesta cubren toda la aritmética.
La trampa de la variable sin inicializar
Este es con diferencia el error de principiante más común en C, y no produce ningún error del compilador:
Ejecútalo. Puede que veas 15, que es la respuesta correcta. Puede que veas un número aleatorio enorme. Puede que veas algo distinto en una segunda ejecución o en otra máquina. Todos esos son comportamientos "correctos", porque leer una variable local sin inicializar es comportamiento indefinido: el estándar de C no impone ningún requisito sobre lo que pasa.
A diferencia de muchos lenguajes, C no pone tus locales a cero. Una variable local es un trozo de la pila, y la pila está llena de restos de llamadas a funciones anteriores. A veces esos restos resultan ser ceros, que es lo que hace tan peligroso este error: a menudo funciona en las pruebas y falla en producción.
La solución es un carácter:
Hazlo un hábito: inicializa cada variable en el punto de su declaración. Si genuinamente no tienes todavía un valor sensato, 0 o NULL son mejores que basura. Y compila con -Wall, que detecta la mayoría de los casos:
warning: 'total' is used uninitialized in this function
Las variables globales y static son la excepción: esas sí se inicializan a cero automáticamente. Apoyarse en eso está bien, pero escribir = 0 de todas formas documenta tu intención.
Declarar varias a la vez
Las variables del mismo tipo pueden compartir una declaración, con o sin inicializadores:
Esto es legal y común para valores muy relacionados como x, y, z. También es donde vive una lectura errónea clásica:
int a = 0, b = 0, c = 0; /* las tres valen 0 */
int d, e, f = 0; /* solo f vale 0: d y e son basura */
El inicializador se adjunta a un nombre, no a la línea. Cuando los valores difieren en significado, dale a cada uno su propia línea: se lee mejor y produce mejores diferencias en el control de versiones.
Declarar punteros en una línea tiene la misma trampa en una forma más aguda:
int *p, q; /* p es un puntero a int; q es un int corriente */
El * se asocia al nombre, no al tipo. Declara los punteros uno por línea.
Reglas y convenciones de nombrado
Las reglas del compilador:
- Solo letras, dígitos y guiones bajos.
- No puede empezar por un dígito:
total2está bien,2totalno. - No puede ser una palabra clave de C: ninguna variable llamada
int,return,forodouble. - Distingue mayúsculas:
count,CountyCOUNTson tres variables distintas. - Los nombres que empiezan por guion bajo, o que contienen un doble guion bajo, están reservados para la implementación. No los crees.
int itemCount; /* legal */
int item_count; /* legal: el estilo habitual de C */
int _count; /* legal pero reservado: evitalo */
int item-count; /* error: '-' es el operador de resta */
int 3rd_place; /* error: empieza por un digito */
int float; /* error: palabra clave */
Las convenciones que sigue la mayoría del código C: snake_case para variables y funciones, MAYUSCULAS para las constantes de macro, y nombres que digan qué significa el valor en lugar de qué tipo es. elapsed_ms le gana a t; customer_count le gana a n2.
Los nombres cortos siguen estando bien donde el ámbito es diminuto: i como contador de bucle se entiende universalmente, y nadie quiere for (int indice_de_iteracion_del_bucle = 0; ...).
Dónde vive una variable
Dónde declaras una variable determina quién puede verla y cuánto dura. Eso es el ámbito, y la versión corta es:
Una variable es visible desde su declaración hasta la llave de cierre del bloque que la contiene. Las globales viven durante todo el programa y son visibles en todas partes, lo que suena cómodo y es por lo que causan problemas: cualquier función puede cambiar una, así que averiguar quién lo hizo se convierte en una búsqueda por todo el archivo. Prefiere las locales y pasa los valores a las funciones como parámetros.
Declarar en cualquier parte (C99 y posteriores)
En el C89 original, toda declaración tenía que ir antes de cualquier sentencia del bloque:
int main(void) {
int i, sum = 0; /* todas las declaraciones primero */
printf("Empezando\n");
for (i = 0; i < 10; i++) { sum += i; }
return 0;
}
Desde C99 puedes declarar donde necesites el valor por primera vez, incluido dentro del encabezado del for:
Este es mejor estilo: la declaración queda junto a su primer uso, e i no puede filtrarse al resto de la función. Compila con -std=c17 (o cualquier configuración de C99 en adelante) y funciona en todas partes.
Preguntas frecuentes
¿Cómo se declara una variable en C?
Escribe el tipo, luego el nombre y luego un punto y coma: int age;. Puedes darle un valor al mismo tiempo —int age = 30;— lo que se llama inicialización y es casi siempre lo que quieres.
¿Cuál es la diferencia entre declarar e inicializar una variable?
Declarar reserva el espacio y le pone nombre (int count;). Inicializar pone un valor dentro en el momento en que se crea (int count = 0;). Una variable local declarada pero sin inicializar contiene los bytes que ya estuvieran en esa dirección: leerla es comportamiento indefinido.
¿Cuáles son las reglas para los nombres de variables en C?
Solo letras, dígitos y guiones bajos; no puede empezar por un dígito; no puede ser una palabra clave como int o for; y distingue mayúsculas de minúsculas, así que total y Total son variables distintas. Los nombres que empiezan por un guion bajo están reservados: evítalos.
¿Se pueden declarar variables en cualquier parte de una función de C?
Desde C99, sí: declara cada variable justo donde la necesites por primera vez. En el estándar original C89 toda declaración tenía que aparecer al inicio de un bloque, que es por lo que el código antiguo tiene un muro de declaraciones antes de cualquier trabajo real.