Constantes float

Del mismo modo, existe una notación especial para las constantes en punto flotante. En este caso consiste en añadir ".0" a aquellas constantes que puedan interpretarse como enteras.

Se puede usar el sufijo "f". En ese caso, se tratará de constantes en precisión sencilla, es decir float.

Por ejemplo:

float x = 0.0;
if(x <= 1.0f) x += 0.01f;

Constantes double

Por defecto, si no se usa el sufijo, el compilador tratará las constantes en precisión doble, es decir double.

Por ejemplo:

double x = 0.0;
if(x <= 1.0) x += 0.01;

Constantes long double

Si se usa el sufijo "L" se tratará de constantes en precisión máxima, es decir long double.

Por ejemplo:

long double x = 0.0L;
if(x <= 1.0L) x += 0.01L;

Constantes enteras

En general podemos combinar los prefijos "0" y "0x" con los sufijos "L", "U", y "UL".

Aunque es indiferente usar los sufijos en mayúsculas o minúsculas, es preferible usar mayúsculas, sobre todo con la "L", ya que la 'l' minúscula puede confundirse con un uno '1'.

Constantes en punto flotante

Ya hemos visto que podemos usar los sufijos "f", "L", o no usar prefijo. En este último caso, cuando la constante se pueda confundir con un entero, debemos añadir el ".0".

Para expresar constantes en punto flotante también podemos usar notación exponencial, por ejemplo:

double x = 10e4;
double y = 4.12e2;
double pi = 3.141592e0;

El formato exponencial consiste en un número, llamado mantisa, que puede ser entero o con decimales, seguido de una letra 'e' o 'E' y por último, otro número, en este caso un número entero, que es el exponente de una potencia de base 10.

Los valores anteriores equivalen a:

x = 10 x 104 = 100000
y = 4,12 x 102 = 412
pi = 3.141592 x 100 = 3.141592

Al igual que con los enteros, es indiferente usar los sufijos en mayúsculas o minúsculas, pero es preferible usar mayúsculas, sobre todo con la "L", ya que la 'l' minúscula puede confundirse con un uno '1'.

Constantes char

Las constantes de tipo char se representan entre comillas sencillas, por ejemplo 'a', '8', 'F'.

Después de pensar un rato sobre el tema, tal vez te preguntes ¿cómo se representa la constante que consiste en una comilla sencilla?. Bien, te lo voy a contar, aunque no lo hayas pensado.

Secuencias de escape

Existen ciertos caracteres, entre los que se encuentra la comilla sencilla, que no pueden ser representados con la norma general. Para eludir este problema existe un cierto mecanismo, llamado secuencias de escape. En el caso comentado, la comilla sencilla se define como '\'', y antes de que preguntes te diré que la barra descendente se define como '\\'.

Pero además de estos caracteres especiales existen otros. El código ASCII, que es el que puede ser representado por el tipo char, consta de 128 ó 256 caracteres. Y aunque el código ASCII de 128 caracteres, 7 bits, ha quedado prácticamente obsoleto, ya que no admite caracteres como la 'ñ' o la 'á'; aún se usa en ciertos equipos antiguos, en los que el octavo bit se usa como bit de paridad en las transmisiones serie. De todos modos, desde hace bastante tiempo, se ha adoptado el código ASCII de 256 caracteres, 8 bits. Recordemos que el tipo char tiene siempre un byte, es decir 8 bits, y esto no es por casualidad.

En este conjunto existen, además de los caracteres alfabéticos, en mayúsculas y minúsculas, los numéricos, los signos de puntuación y los caracteres internacionales, ciertos caracteres no imprimibles, como el retorno de línea, el avance de línea, etc.

Veremos estos caracteres y cómo se representan como secuencia de escape, en hexadecimal, el nombre ANSI y el resultado o significado.

Escape Hexad ANSI Nombre o resultado
  0x00 NULL Carácter nulo
\a 0x07 BELL Sonido de campanilla
\b 0x08 BS Retroceso
\f 0x0C FF Avance de página
\n 0x0A LF Avance de línea
\r 0x0D CR Retorno de línea
\t 0x09 HT Tabulador horizontal
\v 0x0B VT Tabulador vertical
\\ 0x5c \ Barra descendente
\' 0x27 ' Comilla sencilla
\" 0x22 " Comillas
\? 0x3F ? Interrogación
\O   cualquiera O=tres dígitos en octal
\xH   cualquiera H=número hexadecimal
\XH   cualquiera H=número hexadecimal

Los tres últimos son realmente comodines para la representación de cualquier carácter. El \O sirve para la representación en notación octal, la letra 'O' se debe sustituir por un número en octal. Para la notación octal se usan tres dígitos, recuerda que para expresar un byte los valores octales varían de 0 a 0377.

También pueden asignarse números decimales a variables de tipo char. Por ejemplo:

char A;
A = 'a';
A = 97;
A = 0x61;
A = '\x61';
A = 0141;
A = '\141';

En este ejemplo todas las asignaciones son equivalentes y válidas.

Nota: Una nota sobre el carácter nulo. Este carácter se usa en C++ para terminar las cadenas de caracteres, por lo tanto es muy útil y de frecuente uso. Para hacer referencia a él se usa frecuentemente su valor decimal, es decir char A = 0, aunque es muy probable que lo encuentres en libros o en programas como '\000', es decir en notación octal.

Sobre el carácter EOF, del inglés "End Of File", este carácter se usa en muchos ficheros como marcador de fin de fichero, sobre todo en ficheros de texto. Aunque dependiendo del sistema operativo este carácter puede cambiar, por ejemplo en MS-DOS es el carácter "0x1A", el compilador siempre lo traduce y devuelve el carácter EOF cuando un fichero se termina. El valor usado por el compilador está definido en el fichero "stdio.h", y es 0.

¿Por qué es necesaria la notación?

C++ es un lenguaje pensado para optimizar el código y conseguir un buen rendimiento por parte del ordenador cuando ejecute nuestros programas. Esto nos obliga a prestar atención a detalles de bajo nivel (cercanos al hardware), detalles que en otros lenguajes de alto nivel no se tienen en cuenta.

Esto tiene un precio: debemos estar más atentos a los detalles, pero las ventajas compensan, ya que nuestros programas son mucho más rápidos, compactos y eficientes.

En todos estos casos que hemos visto en este capítulo, especificar el tipo de las constantes tiene el mismo objetivo: evitar que se realicen conversiones de tipo durante la ejecución del programa, obligando al compilador a hacerlas durante la fase de compilación.

Esto es una optimización, ya que generalmente, los programas se ejecutan muchas más veces de las que se compilan, así que parece razonable invertir más esfuerzo en minimizar el tiempo de ejecución que el de compilación.

Si en el ejemplo anterior para float hubiéramos escrito if(x <= 1)..., el compilador almacenaría el 1 como un entero, y durante la fase de ejecución se convertirá ese entero a float para poder compararlo con x, que es float. Al poner "1.0" estamos diciendo al compilador que almacene esa constante como un valor en coma flotante, con lo cual nos evitamos la conversión de tipo cada vez que se evalúe la condición de la sentencia if. Lo mismo se aplica a las constantes long, unsigned y char.

Comentarios de los usuarios (3)

Antonio
2013-01-08 16:33:16

Hola de nuevo.

Por lo que explicais en este capitulo entiendo que la notación es simplemente una forma de optimizar el rendimiento.

Si la conversión de octal a binario sustituye cada digito por 3 dígitos vinarios, y la hexadecimal sustitulle cada digito por 4 digitos vinarios:

// 127 en octal a vinario

0177 => 0 = octal; 1 = 001, 7 = 111, 7 = 111 = 01111111

// 127 en hexadecimal a vinario

0x7f => 0x = hexadecimal; 7 = 0111, f = 1111 = 01111111

El hexadecimal necesita menos dígitos para representar y convertir a binario cualquier numero, y por tanto menos cálculos por parte del procesador, en consecuencia optimizaría mas el código.

¿esto seria correcto?

mas dudas:

¿Se puede representar un nº real en octal y hexadecinal?

por ej. imaginemos que quiero asignar el valor 127.127 decimal a un float en hex. y oct.

he intentado hacerlo pero con resultados desastrosos...

En principio no tengo mas dudas al respecto.

Gracias.

Salvador Pozo
2013-01-08 19:05:09

Hola, Antonio:

Lo de optimizar el rendimiento es cierto sólo en parte.

Me explico:

En lo que respecta a usar números en formato decimal, octal o hexadecimal, no afecta para nada al rendimiento, ya que los tres codifican números enteros, y la conversión se hace durante la fase de compilación, de modo que en el ejecutable siempre se almacena el mismo valor, independientemente de la notación que se use en el código fuente.

Este tipo de notaciones está pensada para hacer que el código sea más fácil de leer para los programadores, no para el ordenador.

Las optimizaciones de rendimiento sólo serán patentes cuando la notación afecte al tipo de la constante. Por ejemplo, si vamos a usar una constante para compararla u operar con ella y el otro operando es un entero largo, declararla con el sufijo 'L' obligará al compilador a almacenar un valor de entero largo, y por lo tanto, no tendrá que hacer una promoción implícita en la fase de ejecución. Las promociones implícitas sí requieren cálculos en la fase de ejecución, de modo que si las tenemos previstas en el código optimizaremos el programa cuando se ejecute.

Lo de representar valores en coma flotante usando notación hexadecimal u octal es, cuanto menos, complicado y no se hace nunca. (Yo nunca lo he intentado, ni le veo la utilidad). Recuerda que la notación, en este caso, tiene finalidades documentales.

Antonio
2013-01-08 19:55:36

VALE QUE SI!!

Me estaba complicando la vida al razonar todo esto.

ya veo como funciona y es muy sencillo...

Muchas gracias Salvador. :D