TIPOS Y PRECISIÓN.







Mecanismo de Promoción de Tipos
El formato interno de los diferentes tipos numéricos es radicalmente distinto, según puede comprobarse fácilmente. ¿Cómo es posible entonces que el compilador admita expresiones formadas por distintos tipos de datos numéricos? La respuesta estriba en el modo en que se evalúan las expresiones. El compilador, al detectar la presencia de variables pertenecientes a tipos de datos de diferentes alcances y precisiones, efectúa una transformación interna, obteniendo para cada valor su representación equivalente en el tipo de dato de mayor precisión de los presentes en esa expresión. Acto seguido se efectúan las operaciones (siguiendo las reglas de prioridades de operadores) para producir un resultado final perteneciente al tipo de datos de mayor precisión. Este es el valor que, finalmente, adoptará la expresión. Véase un Ejemplo.

Tabla de Funciones de Comprobación de Tipos
El lenguaje C ofrece una extensa gama de funciones destinadas a comprobar si un determinado valor es representable de acuerdo con un cierto tipo de datos. Véase a continuación una tabla de funciones con sus principales características.

 Prototipo de la función Esta función proporciona el valor verdadero si c es
 int isalnum(int c); Un caracter alfanumérico:[a-z], [A-Z], [0-9]
 int isalpha(int c);  Un carácter alfabético: [a-z], [A-Z].
 int iscntrl(int c);  El carácter de borrado (0x7F) o un carácter de control ordinario entre 0x00 y 0x1F.
 int isdigit(int c);  Un carácter numérico: [0-9].
 int isgraph(int c);  Un carácter imprimible desde el signo de admiración (0x21) hasta la tilde (0x7E).
 int islower(int c);  Una letra minúscula: [a-z].
 int isprint(int c);  Un carácter imprimible desde el espacio (0x20) hasta la tilde (0x7E).
 int ispunct(int c);  Un signo de puntuación, esto es, un carácter que no sea ni un control ni un carácter alfanumérico.
 int isspace(int c);  Un espacio , tabulador, retorno <CR>, salto de línea <LF>, tabulador vertical, <VT>,salto de página <FF>
 int isupper(int c);  Una letra mayúscula [A-Z].
 int isxdigit(int c); Un dígito hexadecimal: [0-9], [A-F], o bien [a-f].

Como ejemplo de aplicación de estas funciones, véase el siguiente Ejercicio.

Ejemplo.- Construir un programa que sume un entero con un real y un real de doble precisión, para almacenar finalmente el resultado en un long double. Comprobar que el compilador no produce errores y que el resultado es correcto.
#include <stdio.h>

int main(void)
{
	int entero;
	float real;
	double real_largo;

	printf ("Mecanismo de promoción de tipos\n\n");
	printf("El tamaño de entero es %d\n", sizeof(entero));
	printf("El tamaño de real es %d\n", sizeof(real));
	printf("El tamaño de real_largo es %d\n", sizeof(real_largo));

	entero = 2;
	real = 4.0;
	real_largo = 8.0;
	
	real = entero + real + real_largo;
	
	printf("La suma de %d + %f + %f es %g\n\n", entero, real, real_largo, real);
	
	printf("\n\nTerminación normal del programa\n\n");
	return 0;
}

/*
Mecanismo de promoción de tipos

El tamaño de entero es 4
El tamaño de real es 4
El tamaño de real_largo es 8
La suma de 2 + 14.000000 + 8.000000 es 14

Terminación normal del programa

*/

Comentarios.- Se han adjuntado las longitudes de los distintos tipos para acentuar lo diferente de su representación interna. En efecto, el resultado es correcto, y su precisión se ajusta a la precisión del lvalue.

Ejercicio.- Construir un programa que muestre el correcto funcionamiento de las funciones de comprobación de tipos.

#include <ctype.h> /* OJO: todas estas macros residen en ctype.h */
#include <stdio.h>
void main(void)
{
 int a = 'F', b = '6', c = '#', d = 9;
 printf("isalnum para %c vale: %d, esto es, %s\n", b, isalnum(b), isalnum(b)?"TRUE":"FALSE");
 printf("isalpha para %c vale: %d, esto es, %s\n", a, isalpha(a), isalpha(a)?"TRUE":"FALSE");
 printf("iscntrl para %c vale: %d, esto es, %s\n", d, iscntrl(d), iscntrl(d)?"TRUE":"FALSE");
 printf("isdigit para %c vale: %d, esto es, %s\n", d, isdigit(d), isdigit(d)?"TRUE":"FALSE");
 printf("isgraph para %c vale: %d, esto es, %s\n", d, isgraph(d), isgraph(d)?"TRUE":"FALSE");
 printf("islower para %c vale: %d, esto es, %s\n", a, islower(a), islower(a)?"TRUE":"FALSE");
 printf("isprint para %c vale: %d, esto es, %s\n", d, isprint(d), isprint(d)?"TRUE":"FALSE");
 printf("ispunct para %c vale: %d, esto es, %s\n", c, ispunct(c), ispunct(c)?"TRUE":"FALSE");
 printf("isspace para %c vale: %d, esto es, %s\n", d, isspace(d), isspace(d)?"TRUE":"FALSE");
 printf("isupper para %c vale: %d, esto es, %s\n", b, isupper(b), isupper(b)?"TRUE":"FALSE");
 printf("isxdigit para %c vale: %d, esto es, %s\n", a, isxdigit(a), isxdigit(a)?"TRUE":"FALSE");
}
/*
isalnum para 6 vale: 16, esto es, TRUE
isalpha para F vale: 128, esto es, TRUE
iscntrl para   vale: 2, esto es, TRUE
isdigit para   vale: 0, esto es, FALSE
isgraph para   vale: 0, esto es, FALSE
islower para F vale: 0, esto es, FALSE
isprint para   vale: 0, esto es, FALSE
ispunct para # vale: 8, esto es, TRUE
isspace para   vale: 2, esto es, TRUE
isupper para 6 vale: 0, esto es, FALSE
isxdigit para F vale: 32, esto es, TRUE
*/

Comentarios.- El operador ? sirve en este caso para generar las cadenas FALSE o TRUE según el valor tomado por la función. Como de costumbre, el valor nulo se toma como FALSE y el valor no nulo se toma como TRUE. Se podría haber construido el programa empleando expresiones de la forma:
	...
	printf("isalnum para %c vale: %d, esto es ", b);
	if (isalnum(b)
		printf("TRUE\n");
	else
		printf("FALSE");
	...


Aunque el resultado sería el mismo, resulta bastante más largo; el operador ?: resulta muy indicado en programas como este.