Curso de CEl Rincón del C - www.elrincondelc.com

Tipos de Datos

[Anterior] [Siguiente] [Contenido]

Contenido del Capítulo

[Arriba]

Introducción

Cuando usamos un programa es muy importante manejar datos. En C podemos almacenar los datos en variables. El contenido de las variables se puede ver o cambiar en cualquier momento. Estas variables pueden ser de distintos tipos dependiendo del tipo de dato que queramos meter. No es lo mismo guardar un nombre que un número. Hay que recordar también que la memoria del ordenador es limitada, así que cuando guardamos un dato, debemos usar sólo la memoria necesaria. Por ejemplo si queremos almacenar el número 400 usaremos una variable tipo int (la estudiamos más abajo) que ocupa sólo 16 bits, y no una de tipo long que ocupa 32 bits. Si tenemos un ordenador con 32Mb de Ram parece una tontería ponernos a ahorrar bits (1Mb=1024Kb, 1Kb=1024bytes, 1byte=8bits), pero si tenemos un programa que maneja muchos datos puede no ser una cantidad despreciable. Además ahorrar memoria es una buena costumbre.

(Por si alguno tiene dudas: No hay que confundir la memoria con el espacio en el disco duro. Son dos cosas distintas. La capacidad de ambos se mide en bytes, y la del disco duro suele ser mayor que la de la memoria Ram. La información en la Ram se pierde al apagar el ordenador, la del disco duro permanece. Cuando queremos guardar un fichero lo que necesitamos es espacio en el disco duro. Cuando queremos ejecutar un programa lo que necesitamos es memoria Ram. La mayoría me imagino que ya lo sabeís, pero me he encontrado muchas veces con gente que los confunde.)

[Arriba]

Notas sobre los nombres de las variables

A las variables no se les puede dar cualquier nombre. No se pueden poner más que letras de la 'a' a la 'z' (la ñ no vale), números y el símbolo '_'. No se pueden poner signos de admiración, ni de interrogación... El nombre de una variable puede contener números, pero su primer carácter no puede serlo.

Ejemplos de nombres válidos:

	camiones
	numero
	buffer
	a1
	j10hola29
	num_alumnos
Ejemplos de nombres no válidos:
	1abc
	nombre?
	num/alumnos

Tampoco valen como nombres de variable las palabras reservadas que usa el compilador. Por ejemplo: for, main, do, while.

Por último es interesante señalar que el C distingue entre mayúsculas y minúsculas. Por lo tanto:

	Nombre
	nombre
	NOMBRE

serían tres variables distintas.

[Arriba]

El tipo Int

En una variable de este tipo se almacenan números enteros (sin decimales). El rango de valores que admite es -32767 a 32767. Cuando definimos una variable lo que estamos haciendo es decirle al compilador que nos reserve una zona de la memoria para almacenar datos de tipo int. Para guardarla necesitaremos 16 bits de la memoria del ordenador (216=32767). Para poder usar una variable primero hay que declararla (definirla). Hay que decirle al compilador que queremos crear una variable y hay que indicarle de qué tipo. Por ejemplo:

int numero;

Esto hace que declaremos una variable llamada numero que va a contener un número entero.

¿Pero dónde se declaran las variables?

Tenemos dos posibilidades, una es declararla como global y otra como local. Por ahora vamos a decir que global es aquella variable que se declara fuera de la función main y local la que se declara dentro:

Variable GlobalVariable Local
#include <stdio.h>

int x;

int main()
	{
	}

#include <stdio.h>

int main()
	{
	int x;
	}

La diferencia práctica es que las variables globales se pueden usar en cualquier procedimiento. Las variables locales sólo pueden usarse en el procedimiento en el que se declaran. Como por ahora sólo tenemos el procedimiento (o función, o rutina, o subrutina, como prefieras) main esto no debe preocuparnos mucho por ahora. Cuando estudiemos cómo hacer un programa con más funciones aparte de main volveremos sobre el tema. Sin embargo debes saber que es buena costumbre usar variables locales que globales. Ya veremos por qué.

Podemos declarar más de una variable en una sola línea:

	int x, y;

Mostrar variables por pantalla

Vamos a ir u poco más allá con la función printf. Supongamos que queremos mostrar el contenido de la variable

x
por pantalla:
	printf( "%i", x );

Suponiendo que x valga 10 (x=10) en la pantalla tendríamos:

	10

Empieza a complicarse un poco ¿no? Vamos poco a poco. ¿Recuerdas el símbolo "\" que usábamos para sacar ciertos caracteres? Bueno, pues el uso del "%" es parecido. "%i" no se muestra por pantalla, se sustituye por el valor de la variable que va detrás de las comillas. ( %i, de integer=entero en inglés).

Para ver el contenido de dos variables, por ejemplo x e y, podemos hacer:

	printf( "%i ", x );
	printf( "%i", y );

resultado (suponiendo x=10, y=20):

	10 20

Pero hay otra forma mejor:

	printf( "%i %i", x, y );

... y así podemos poner el número de variables que queramos. Obtenemos el mismo resultado con menos trabajo. No olvidemos que por cada variable hay que poner un %i dentro de las comillas.

También podemos mezclar texto con enteros:

	printf( "El valor de x es %i, ¡que bien!\n", x );

que quedará como:

	El valor de x es 10, ¡que bien!

Como vemos %i al imprimir se sustituye por el valor de la variable.

Asignar valores a variables de tipo int

La asignación de valores es tan sencilla como:

	x = 10;

También se puede dar un valor inicial a la variable cuando se define:

	int x = 15;

También se pueden inicializar varias variables en una sola línea:

	int x = 15, y = 20;

Hay que tener cuidado con lo siguiente:

	int x, y = 20;

Podríamos pensar que x e y son igual a 20, pero no es así. La variable x está sin valor inicial y la variable 'y' tiene el valor 20.

Veamos un ejemplo para resumir todo:

#include <stdio.h>

int main()
	{
	int x = 10;

	prinft( "El valor inicial de x es %i\n", x );
	x = 50;
	printf( "Ahora el valor es %i\n", x );
	}

Cuya salida será:

	El valor inicial de x es 10
	Ahora el valor es 50

Importante! Si imprimimos una variable a la que no hemos dado ningún valor no obtendremos ningún error al compilar pero la variable tendrá un valor cualquiera. Prueba el ejemplo anterior quitando

int x = 10;

Puede que te imprima el valor 10 o puede que no.

[Arriba]

El tipo Char

Las variables de tipo char sirven para almacenar caracteres. Los caracteres se almacenan en realidad como números del 0 al 255. Los 128 primeros (0 a 127) son el ASCII estándar. El resto es el ASCII extendido y depende del idioma y del ordenador. Consulta la tabla ASCII en el anexo.

Para declarar una variable de tipo char hacemos:

	char letra;

En una variable char sólo podemos almacenar solo una letra, no podemos almacenar ni frases ni palabras. Eso lo veremos más adelante (strings, cadenas). Para almacenar un dato en una variable char tenemos dos posibilidades:

	letra = 'A';
o
	letra = 65;

En ambos casos se almacena la letra 'A' en la variable. Esto es así porque el código ASCII de la letra 'A' es el 65.

Para imprimir un char usamos el símbolo %c (c de character=caracter en inglés):

	letra = 'A';
	printf( "La letra es: %c.", letra );

resultado:

	La letra es A.

También podemos imprimir el valor ASCII de la variable usando %i en vez de %c:

	letra = 'A';
	printf( "El número ASCII de la letra %c es: %i.", letra, letra );

resultado:

	El código ASCII de la letra A es 65.

Como vemos la única diferencia para obtener uno u otro es el modificador (%c ó %i) que usemos.

Las variables tipo char se pueden usar (y de hecho se usan mucho) para almacenar enteros. Si necesitamos un número pequeño (entre -127 y 127) podemos usar una variable char (8bits) en vez de una int (16bits), con el consiguiente ahorro de memoria.

Todo lo demás dicho para los datos de tipo

int
se aplica también a los de tipo
char
.

Una curiosidad:

	letra = 'A';
	printf( "La letra es: %c y su valor ASCII es: %i\n", letra, letra );
	letra = letra + 1;
	printf( "Ahora es: %c y su valor ASCII es: %i\n", letra, letra );

En este ejemplo letra comienza con el valor 'A', que es el código ASCII 65. Al sumarle 1 pasa a tener el valor 66, que equivale a la letra 'B' (código ASCII 66). La salida de este ejemplo sería:

La letra es A y su valor ASCII es 65
Ahora es B y su valor ASCII es 66

[Arriba]

El modificador Unsigned

Este modificador (que significa sin signo) modifica el rango de valores que puede contener una variable. Sólo admite valores positivos. Si hacemos:

	unsigned char variable;

Esta variable en vez de tener un rango de -128 a 128 pasa a tener un rango de 0 a 255.

[Arriba]

El tipo Float

En este tipo de variable podemos almacenar números decimales, no sólo enteros como en los anteriores. El rango de posibles valores es del 3,4E-38 al 3,4E38.

Declaración de una variable de tipo float:

	float numero;

Para imprimir valores tipo float Usamos %f.

	float num=4060.80;
	printf( "El valor de num es : %f", num );

Resultado:

	El valor de num es: 4060.80

Si queremos escribirlo en notación exponencial usamos %e:

	float num = 4060.80;
	printf( "El valor de num es: %e", num );

Que da como resultado:

	El valor de num es: 4.06080e003

[Arriba]

El tipo Double

En las variables tipo double se almacenan números reales del 1,7E-307 al 1,7E308. Se declaran como double:

	double numero;

Para imprimir se usan los mismos modificadores que en float.

[Arriba]

Cómo calcular el máximo valor que admite un tipo de datos

Lo primero que tenemos que conocer es el tamaño en bytes de ese tipo de dato. Vamos a ver un ejemplo con el tipo INT. Hagamos el siguiente programa:

#include <stdio.h>

int main()
     {
     int num1;

     printf( "El tipo int ocupa %i bytes\n", sizeof(int) );
     }
Comprobado con DJGPP

En mi ordenador el resultado es:

El tipo int ocupa 4 bytes.

Como sabemos 1byte = 8bits. Por lo tanto el tipo int ocupa 4*8=32 bits.

Ahora para calcular el máximo número debemos elevar 2 al número de bits obtenido. En nuestro ejemplo: 2^32=4.294.967.296. Es decir en un int se podría almacenar un número entre 0 y 4.294.967.296.

Sin embargo esto sólo es cierto si usamos un tipo unsigned (sin signo, se hace añadiendo la palabra unsigned antes de int). Para los tipos normales tenemos que almacenar números positivos y negativos. Así que de los 4.294.967.296 posibles números la mitad serán positivos y la mitad negativos. Por lo tanto tenemos que dividir el número anterior entre 2 = 2.147.483.648. Como el 0 se considera positivo el rango de números posibles que se pueden almacenar en un int sería: -2.147.483.648 a 2.147.483.647.

Resumen:

  1. Obtenemos el número de bytes.
  2. Multiplicamos por ocho (ya lo tenemos en bits).
  3. Elevamos 2 al número de bits.
  4. Dividimos entre 2.

[Arriba]

Overflow: Qué pasa cuando nos saltamos el rango

El overflow es lo que se produce cuando intentamos almacenar en una variable un número mayor del máximo permitido. El comportamiento es distinto para variablesde números enteros y para variables de números en coma flotante.

Con números enteros

En mi ordenador y usando DJGPP bajo Dos el tamaño del tipo int es de 4bytes(4*8=32bits). El número máximo que se puede almacenar en una variable tipo int es por tanto 2.147.483.647 (ver apartado anterior). Si nos pasamos de este número el que se guardará será el siguiente pero empezando desde el otro extremo, es decir, el -2.147.483.648. El compilador seguramente nos dará un aviso (warning) de que nos hemos pasado.

#include <stdio.h>

int main()
     {
     int num1;

     num1 = 2147483648;
     printf( "El valor de num1 es: %i\n", num1 );
     }
Comprobado con DJGPP

El resultado que obtenemos es:

El valor de num1 es: -2147483648

Comprueba si quieres que con el número anterior (2.147.483.647) no pasa nada.

Con números en coma flotante

El comportamiento con números en coma flotante es distinto. Dependiendo del ordenador si nos pasamos del rango al ejecutar un programa se puede producir un error y detenerse la ejecución.

Con estos números también existe otro error que es el underflow. Este error se produce cuando almacenamos un número demasiado pequeño (3,4E-38 en float).

[Arriba]

Resumen de los tipos de datos en C

Esto es algo orientativo, depende del sistema.

TipoDatos almacenadosNº de BitsValores posibles (Rango)Rango usando unsigned
charCaracteres8-128 a 1280 a 255
intenteros16-32.767 a 32.7670 a 65.535
longenteros largos32-2.147.483.647 a 2.147.483.6470 a 4.294.967.295
floatNums. reales (coma flotante)323,4E-38 a 3,4E38
doubleNums. reales (coma flotante doble)641,7E-307 a 1,7E308

Esto no siempre es cierto, depende del ordenador y del compilador. Para saber en nuestro caso qué tamaño tienen nuestros tipos de datos debemos hacer lo siguiente. Ejemplo para int:

	#include <stdio.h>

	int main()
		{
		printf( "Tamaño (en bits) de int = %i\n", sizeof( int )*8 );
		
		return 0;
		}

Ya veremos más tarde lo que significa sizeof. Por ahora basta con saber que nos dice cual es el tamaño de una variable o un tipo de dato.

[Arriba]

Ejercicios

Ejercicio 1. Busque los errores:

	#include <stdio.h>

	int main()
		{
		int número;

		número = 2;
		
		return 0;
		}

Solución: Los nombres de variables no pueden llevar acentos, luego al compilar número dará error.

	#include <stdio.h>

	int main()
		{
		int numero;

		numero = 2;

		printf( "El valor es %i" Numero );
		
		return 0;
		}

Solución: Falta la coma después de "El valor es %i". Además la segunda vez numero está escrito con mayúsculas.

[Anterior] [Siguiente] [Contenido]

© Gorka Urrutia

www.elrincondelc.com