Los lenguajes de alto nivel facilitan mucho la creación y mantenimiento de variables. Desde un punto de vista estrictamente de bajo nivel, sería responsabilidad del programador reservar posiciones concretas de memoria para usarlas como variables, y también debería recordar sus direcciones, para poder acceder a ésas variables, indicando la dirección en una instrucción de lenguaje máquina.
Esta labor se complica al crecer el número de variables, de las que hay que recordar no sólo su dirección, sino también su extensión y su tipo. Para un ser humano, resulta mucho más fácil recordar un nombre que un número, y los lenguajes de alto nivel facilitan mucho la tarea al permitirnos acceder a una variable mediante un nombre, y no mediante una dirección.
Una variable es un espacio reservado en la memoria con un nombre simbólico (identificador), en el cual podemos almacenar un valor de un tipo específico. Las variables nos permiten almacenar datos temporales que podemos utilizar posteriormente a lo largo de nuestro programa. En este sentido, lo único que necesita conocer un compilador de C para crear una variable es el tipo al que pertenece y el nombre que se le quiere dar; el compilador se encarga de mantener la tabla de variables, y de asociar a cada nombre la dirección correspondiente.
Sintaxis y Reglas para Declarar Variables
El lenguaje C obliga a declarar una variable antes de ser usada. Es decir, no podríamos escribir algo del tipo: Mostrar velocidad01, si antes no hemos “dicho” (declarado) que existe una variable con ese nombre.
Conociendo ya los tipos de variables básicas y cómo nombrarlas, veamos ahora cómo declararlas. La declaración de variables en C tradicionalmente se hace al principio del programa. Para facilitar la corrección y claridad de nuestros programas, el lugar donde realizaremos la declaración de variables, al menos de momento, será después de la línea int main(), que constituye el inicio del código ejecutivo de nuestro programa.
Lea también: Aspectos Clave del Código Tributario de Panamá
La sintaxis básica para declarar una variable es la siguiente:
tipo_base nombre_variable;
Donde tipo_base es cualquier tipo válido de C y nombre_variable es un identificador válido en C. Un identificador es una letra seguida opcionalmente por otras letras y números. Téngase en cuenta que no se admiten signos diacríticos (acentos, tildes, etc.) y que las letras mayúsculas y minúsculas no se consideran equivalentes. Por otra parte, no se admite utilizar como identificadores los nombres de palabras reservadas en C.
Una variable puede tener cualquier nombre conformado por letras y/o números, que no incluya espacios, símbolos especiales, sea una palabra reservada del compilador (como el tipo de variable), ya lo tenga otra variable o función, o sea enteramente compuesta por números. La prueba más clara de esto es que la declaración terminará con un ";".
En C podemos declarar variables en múltiples líneas, una por línea, pero también varias variables en una línea. Podemos además declarar varias variables del mismo tipo separándolas con comas.
Lea también: CP Ex Hacienda San Juan De Dios CDMX
Inicialización de Variables
Declarar una variable no significa que se le asigne contenido, sino simplemente se indica que la variable existe. Cuando se declara una variable, su contenido no está definido en general; téngase en cuenta que lo que ha hecho el compilador es reservar espacio y es muy posible que se estén reutilizando posiciones de memoria empleadas anteriormente por otro programa. Esas posiciones pueden contener cualquier trama de bits, que podría corresponder a un valor sin sentido para nuestros propósitos.
Si utilizamos la variable sin darle valor nosotros mismos, corremos el riesgo de que adopte un valor incorrecto. Consiguientemente, es preciso dar valores a las variables antes de utilizarlas. En C no está permitido usar una variable sin antes haberle asignado un contenido, a lo que se denomina “inicializar la variable”. Por tanto, al tratar de ejecutar un programa donde una variable está sin inicializar puede producirse un error de compilación. Nosotros vamos a trabajar con C por lo que habremos de declarar e inicializar las variables que usemos siempre.
También es posible declarar e inicializar una variable en una sola línea, lo cual facilita la escritura de código:
tipo_base nombre_variable = valor;
Evidentemente, el valor asignado tiene que pertenecer al tipo de la variable declarada. En el caso de que la variable sea estructurada, es preciso escribir los valores correspondientes entre llaves, y separados mediante comas. La asignación de valores a los distintos elementos de la variable estructurada se realiza por orden cronológico (por filas, para ser exactos), y por tanto será preciso respetar el número y tipo de los elementos que formen esa variable estructurada.
Lea también: ¿Cuál es el Código Postal de Hacienda El Rosario, Nuevo León?
Tipos de Variables en C
Cuando nos referimos a tipos de variables, en realidad nos estamos refiriendo a distintos tipos de valores que una variable puede tener. El lenguaje C posee una notable cantidad de tipos de datos, con objeto de abarcar distintas gamas de alcances con distintos consumos de memoria. El compilador se asegura de que las operaciones realizadas con estas variables sean las adecuadas para su tipo; por ejemplo, no permitirá almacenar un char en un float, ni concatenar dos int.
Cada tipo de variable tiene un tamaño en bits. De esta manera, si quisiéramos saber cuál es el valor que una determinada variable puede tener, basta con hacer la operación \(2^n\) donde \(n\) es el tamaño en bits que la computadora asigna a cada uno. Como hemos estado viendo, los valores de las variables se ven reducidos de su máximo posible en bits porque usamos signos positivo y negativo. Si sólo usáramos signos positivos, tendríamos más espacio para valores más grandes, de la totalidad de sus bits. Por defecto, los tipos son signed (con signo), pero se puede especificar explícitamente, por ejemplo, signed int T=1;, aunque no es necesario escribirse.
Tipos Enteros
El lenguaje C posee una notable cantidad de tipos de datos enteros, con objeto de abarcar distintas gamas de alcances (con distintos consumos de memoria, claro está).
La siguiente tabla muestra algunos de los tipos enteros más comunes en C, junto con su tamaño y rango aproximado (los rangos pueden variar ligeramente entre compiladores y arquitecturas):
| Tipo | Tamaño (bytes) | Rango (con signo) | Rango (sin signo) |
|---|---|---|---|
| char | 1 | -128 a 127 | 0 a 255 |
| short | 2 | -32768 a 32767 | 0 a 65535 |
| int | 4 | -2,147,483,648 a 2,147,483,647 | 0 a 4,294,967,295 |
| long | 4 u 8 | Al menos como int (puede ser igual a int o long long) | Al menos como unsigned int |
| long long | 8 | -9,223,372,036,854,775,808 a 9,223,372,036,854,775,807 | 0 a 18,446,744,073,709,551,615 |
Los tipos long long y unsigned long long pueden no encontrarse en todos los compiladores, ya que fueron estandarizados en versiones posteriores de C (C99).
Otros Tipos de Datos
- char: Para valores tipo carácter. Un carácter es un símbolo, como los que usamos para escribir, por ejemplo ‘T’, ‘c’, ‘r’, ‘/’, ‘5’. Una variable de este tipo lo que almacena en sí es un número con base decimal, un código que está asociado a un carácter.
- float: Para valores decimales, con hasta 6 decimales de precisión.
- double: Para valores decimales, con una exactitud de hasta 15 dígitos después del punto decimal.
Variables Booleanas
A diferencia de la mayoría de lenguajes, C no incorpora entre sus tipos predefinidos el tipo booleano (true / false). El motivo para ello es que en realidad no es estrictamente necesario para permitir la programación, ya que puede emularse fácilmente por ejemplo usando un entero al que asignamos valor uno o valor cero según sea verdadera o falsa una condición. Por ejemplo, bool algo=23; se interpretará como true cuando se asigne a una variable tipo booleana cualquier valor distinto de \(0\); cuando se le da este valor se tomará como de tipo false.
Cadenas de Caracteres (Strings)
Una peculiaridad de C respecto a otros lenguajes es que no tiene un tipo predefinido “String” o cadena de caracteres. Aunque sí dispone de distintas funciones relacionadas con cadenas, cuando queramos declarar una variable como tipo alfanumérico tendremos que hacerlo declarando un array de caracteres. Es decir, en C las cadenas se declaran como vectores de tipo char. Por ejemplo, la palabra “curso” estaría formada por cinco caracteres que son ‘c’, ‘u’, ‘r’, ‘s’, ‘o’.
Consideraciones al Elegir un Tipo
Es importante elegir siempre el tipo de variable más sencillo posible. Consideraremos que el grado de sencillez viene definido por la memoria requerida (a menor memoria requerida, mayor es la sencillez). Podríamos utilizar siempre variables tipo long long y así no preocuparnos mucho por los valores que pueda tener una variable de este tipo; sin embargo, esto usaría más memoria de la que suele ser necesaria.
En el caso de asignar un valor de un tipo diferente, como por ejemplo int C=9.21;, solo se guardará la parte entera de la asignación.
Ámbito de las Variables
Las tablas de variables pueden ser propias de una función, o bien pueden recoger las variables declaradas fuera de toda función, constituyendo la tabla de variables globales. Hay una tercera regla, que hace referencia a la situación de la declaración con respecto al lugar en que se quiera utilizar lo declarado.
Variables Locales
Aquellas variables que se declaren dentro del programa principal (entre las llaves de main(), en este caso) serán variables locales de la función main(), y por tanto resultarán invisibles para cualquier otro subprograma. Obsérvese que en las funciones se han definido variables locales (a y b); estas variables locales pertenecen al espacio de nombres de cada función, y por tanto se trata de variables distintas e independientes aunque se les dé igual nombre.
Variables Globales
Aquellas variables que se declaren fuera de main(), serán variables globales dentro del fichero en que reside el programa. Esto es, todas las funciones declaradas dentro de ese fichero podrán utilizar las variables globales como si fuesen propias; esto sirve para intercambiar información entre funciones, pero puede suponer un riesgo de corrupción de información si una función hace uso inadvertidamente de una variable global en lugar de emplear una variable local.
Visibilidad
Para que lo declarado (la variable, prototipo o lo que sea) resulte visible para otro objeto del mismo ámbito local o global, es necesario que la declaración sea cronológicamente previa al lugar en que se quiera utilizar.
Constantes en C
Las datos constantes, mal llamadas por algunos "variables constantes" (realmente no son variables), tienen un valor fijo durante toda la ejecución del programa, es decir, este valor no cambia ni puede ser cambiado a lo largo de la ejecución de nuestro programa. Las constantes son muy útiles para especificar el tamaño de un vector y para algunas otras cosas, como facilidad de uso y confiabilidad del código.
En C, la instrucción #define nos permite declarar constantes de una manera rápida y sencilla. Hay que tener en cuenta que al declarar constantes con #define debemos hacerlo después de los #include para importar librerías, pero antes de declarar nuestras funciones y demás. Por ejemplo, el número pi es un valor constante, por lo que podremos declararlo como una constante en lugar de como una variable.
Entrada y Salida de Datos con Variables
El lenguaje C carece de operaciones propias de E/S; esto se hizo para hacerlo independiente de las máquinas en que se utilizaría, y exige crear para cada máquina las funciones de entrada/salida necesarias. Esas funciones se declaran en un archivo de encabezado, stdio.h, y esta es la razón por la cual se incluye ese archivo en todos los programas que contengan operaciones de entrada/salida.
Las funciones más comunes para la entrada y salida de datos son printf() y scanf().
La función printf()
La función printf() se utiliza para mostrar datos en la consola. Su sintaxis básica incluye una cadena de formato y una lista de variables:
printf("cadena_de_formato", lista_de_variables);
cadena_de_formato es una cadena de caracteres (una colección de letras y números encerrada entre comillas) que indica la forma en que hay que escribir en pantalla las variables que aparezcan en el segundo argumento (lista_de_variables). En general, la cadena_de_formato contiene una información literal, que se reproducirá sin cambio alguno, y una información de formato, que se empleará para dar formato únicamente a las variables situadas en posiciones homólogas dentro de la lista de variables.
Quierese decir que si la cadena de formato tiene tres indicadores de formato (se reconocen fácilmente porque empiezan por el signo de %), entonces el primer indicador se empleará para dar formato a la primera variable; el segundo afectará al formato de la segunda variable, y el tercero se empleará para dar formato a la tercera variable. Si sobran formatos (faltan variables), el resultado es imprevisible. Si sobran variables, se imprimen los valores de aquellas variables para las cuales hay especificador de formato, y no se imprimen las restantes.
Los indicadores de formato comienzan por el signo %, y van seguidos por caracteres que indican el tipo de formato que debe darse a la variable correspondiente. En el caso de las variables enteras, las letras que hay que utilizar son d o ld (%d o bien %ld), en función de la longitud del tipo entero empleado. Los compiladores actuales producen resultados correctos para ambos tipos de enteros empleando el factor de conversión %d.
La lista_de_variables es una colección de variables formada por uno o más elementos separados mediante comas. Se admiten tanto los nombres de variables explícitas como los punteros de char (que se interpretan como dirección de comienzo de una cadena de caracteres). Téngase en cuenta que el compilador utilizará los descriptores homólogos, sin importarle que coincidan correctamente los tipos. Los resultados son a menudo interesantes, pero no los esperados. Un ejemplo sería: printf("Alfa vale %d, beta vale %d y delta vale %d. Alfa vale 1, beta vale 2 y delta vale 3."
Este programa muestra la aplicación práctica de los distintos formatos de lectura y escritura necesarios para manejar los tipos enteros disponibles en C.
La función scanf()
Las operaciones de lectura de enteros son similares a las de escritura. La función scanf() se utiliza para leer datos del teclado. Su sintaxis es similar a printf(), pero requiere las direcciones de las variables para almacenar los valores leídos:
scanf("cadena_de_formato", lista_de_direcciones);
Lista_de_direcciones es una colección de direcciones de variables (estáticas o dinámicas) que scanf() emplea como destino de la información leída a partir del teclado, una vez traducida, si procede, al formato especificado en el descriptor correspondiente.
Dicho de otro modo, scanf() cree firmemente que las direcciones que se le proporcionan corresponden a variables de tipo correcto y extensión suficiente para almacenar el resultado de la lectura. Si se lee más información que la que cabe en la variable señalada por una dirección, los resultados son imprevisibles y generalmente negativos. Si el programador sospecha que hay peligro de entrada de datos excesiva y/o incorrectos, procederá a emplear la función fgets() para limitar la extensión de la cadena leída, realizando después una traducción al formato oportuno mediante funciones como strtol(), strtof(), etc.
Operaciones con Enteros en C
Como cabía esperar de un lenguaje destinado a la programación de sistemas, C permite manipular enteros de forma rápida y flexible. Los operadores aritméticos de tratamiento de enteros admiten cualquier tipo de entero, y permiten evaluar expresiones mixtas (con distintos tipos de enteros) siguiendo el principio de promoción de tipos: todos los valores se traducen temporalmente al tipo de mayor precisión; luego se efectúan las operaciones y se traduce automáticamente el resultado al tipo de destino. El objetivo de este procedimiento es no perder nunca información por efectuar operaciones con tipos de menor precisión que pudieran dar lugar a desbordamientos.
El operador módulo (%) proporciona el resto de la división entera de sus dos operandos; por ejemplo, 7 % 5 es 2. Un ejemplo de su uso sería: if (a % b == 0) printf("%d no es primo porque es divisible por %d", a, b); Esta sentencia imprimirá en pantalla un mensaje si el resto de dividir a por b es cero, esto es, si a es divisible por b.
Este programa muestra el uso de operaciones con números enteros, y permite verificar fácilmente lo que sucede en caso de desbordamiento. Por ejemplo, ¿qué sucede cuando se suman dos números mayores que 16384? Téngase en cuenta que hemos utilizado deliberadamente enteros del tipo short, cuyo rango de validez oscila entre -32768 y 32767. Nuestro objetivo era comprobar los problemas que surgen cuando se produce un desbordamiento, y esto se ha mostrado haciendo uso de valores que sobrepasan precisamente en una unidad el mayor valor admisible para los distintos tipos enteros. En todos los casos, el programa sigue su ejecución sin mostrar ninguna indicación de fallo, pero los resultados carecen de sentido. Por tanto, será preciso asegurarse de que las operaciones realizadas no puedan dar lugar a este tipo de circunstancias. Ciertamente procede un comentario tranquilizador: como puede observarse, C ofrece tipos de datos enteros de alcance tan grande que sería preciso abordar problemas de Física o de Matemáticas para alcanzar sus límites.
Comentarios en C
El concepto de comentario, presente en todos los lenguajes de programación, tiene una importancia mayor que la que pudiera otorgársele a primera vista. Un comentario es un mensaje del programador para otros programadores posteriores, o quizá para sí mismo al cabo de algún tiempo. En este mensaje se justifican las decisiones de codificación tomadas, esto es, se exponen las razones que impulsan al programador a emplear una cierta estructura de programa, frente a otras posibles.
Estas explicaciones son valiosísimas, porque suele ser difícil interpretar el código construido por un desconocido cuando, además, el algoritmo que pretende implementar no resulta especialmente claro. En los comentarios de programa se debe incluir toda información que pueda resultar necesaria para posteriores programadores que necesiten comprender nuestro código, bien sea para emplear sus resultados o para introducir modificaciones. Estos comentarios forman parte de la Documentación del programa, y describen internamente el código fuente.
En C, los comentarios se denotan encerrando el texto correspondiente entre los signos /* y */. Por ejemplo: /*Esto es un comentario de una línea.
