2.2.3 Modificadores de tipo
§1 Sinopsis
Hemos señalado ( 2.2.1) que los modificadores opcionales que pueden acompañar a los tipos básicos son: con signo, sin signo, largo y corto; y que se aplican con las palabras clave. long, short, signed, unsigned. Por otra parte, la creciente implementación de procesadores con longitud de palabra de 64 bits, hace suponer que pronto se extenderán los tipos actuales incluyendo versiones extra-largas de los enteros ( Tipos extendidos).
§2 long
Sintaxis:
long [int] <identificador> ;
[long] double <identificador> ;
Descripción:
Cuando se utiliza este modificador sobre un int, crea un tipo que dobla el espacio de almacenamiento utilizado para almacenar un int [1]. Cuando se utiliza para modificar un double, define un tipo de dato de coma flotante, long double, con 80 bits de precisión, no los 128 (2x64) que cabría esperar ( 2.2.4 Representación interna y precisión).
Existen los siguientes tipos de long:
long x; // x es signed long int
long int x; // x es signed long int
signed long x; // x es signed long int
signed long int x; // x es signed long int
unsigned long x; // x es unsigned long int
unsigned long int x; // x es unsigned long int
§3 short
Sintaxis:
short int <identificador> ;
Descripción:
El modificador short se utiliza cuando se desea una variable menor que un int. Este modificador solo puede aplicarse al tipo base int (si se omite el tipo base, se asume int por defecto).
Existen los siguientes tipos:
short x; // x es signed short int
short int x; // x es signed short int
signed short x; // x es signed short int
signed short int x; // x es signed short int
unsigned short x; // x es unsigned short int
unsigned short int x; // x es unsigned short int
Ejemplos:
short int i;
short i; // equivale a: "short int i;"
§4 signed
Sintaxis:
signed <tipo> <identificador> ;
Descripción:
El modificador de tipo signed define que el valor de una variable numérica puede ser positivo o negativo. Este modificador puede ser aplicado a los tipos básicos int, char, long, short y __int64. Según se indica en el ejemplo, si no se indica el tipo básico, el modificador por si solo supone signed int.
El efecto que tiene este modificador, es que parte de la capacidad de almacenamiento del tipo base al que se aplica, se utiliza para especificar el signo, por lo que el máximo valor absoluto que es posible guardar es menor que el correspondiente valor unsigned del mismo tipo base ( 2.2.4 Tipos de datos y representación interna).
Ejemplos:
signed int i; // signed es valor por defecto (no es preciso)
int i; // equivalente al anterior
signed i; // equivalente al anterior
unsigned long int l; // Ok
unsigned long l; // equivale al anterior
signed char ch; // Ok
unsigned char ch; // Ok
§5 unsigned
Sintaxis:
unsigned <tipo> <identificador> ;
Descripción:
Este modificador se utiliza cuando la variable sea siempre positiva. Puesto que no es necesario almacenar el signo, el valor absoluto puede ser mayor que en las versiones con signo. Puede aplicarse a los tipos base int, char, long, short e __int64. Cuando no se indica tipo base, por defecto se supone que se trata de un int (ver los ejemplos).
Ejemplos:
unsigned int i;
unsigned i; // equivale al anterior
unsigned long int l; // Ok
unsigned long l; // Equivale al anterior
unsigned char ch; // Ok
char ch; // Equivale al anterior
§6 Tipos enteros extendidos
La progresiva utilización de procesadores de 64 bits, de los que pronto existirán versiones para ordenadores de sobremesa, junto con el crecimiento espectacular de la memoria disponible, tanto en RAM como en disco, hace que sea razonable esperar versiones de C++ que permitan utilizar enteros con más de 32 bits. Entre otras razones, porque rápidamente serán normales almacenamientos de disco con más capacidad de la que puede direccionarse directamente con palabras de 32 bits.
En la actualidad se está trabajando en un estándar, conocido como C9x que se espera sea adoptado oficialmente en breve (2001). Esta versión incluye nuevos especificadores opcionales long long en versiones con y sin signo [2].
El cuadro adjunto muestra la propuesta existente para los citados modificadores. Como puede verse, siguiendo la tradición, se supone int si no se indica otro tipo base. Además por defecto long long se supone con signo.
long long x; // x es signed long long int
long long int x; // x es signed long long int
signed long long x; // x es signed long long int
signed long long int x; // x es signed long long int
unsigned long long x; // x es unsigned long long int
unsigned long long int x; // x es unsigned long long int
§7 Extensiones C++Builder
Este compilador C++ de Borland permite especificadores opcionales para los enteros, más allá de lo especificado en el estándar (alguno en línea de los nuevos tipos que se esperan). Estos modificadores opcionales permiten definir el tipo de almacenamiento que se utilizará para el entero. Para utilizarlos es preciso usar también los sufijos que se indican en cada caso:
Tipo | Sufijo | Ejemplo | Almacenamiento |
__int8 | i8 | __int8 c = 127i8; | 8 bits |
__int16 | i16 | __int16 s = 32767i16; | 16 bits |
__int32 | i32 | __int32 i = 123456789i32; | 32 bits |
__int64 | i64 | __int64 big = 12345654321i64; | 64 bits |
unsigned __int64 | ui64 | unsigned __int64 hInt=1234567887654321ui64; | 64 bits |
[1] Esto no es exactamente cierto en los compiladores de 32 bits, donde int y long int tienen 32 bits en ambos casos. En realidad el estándar hace muy pocas asunciones sobre el tamaño de los diversos tipos.
[2] Aunque no sea todavía un estándar, en la actualidad esta posibilidad ya está siendo ofrecida por algunos compiladores aunque bajo otros nombres. Por ejemplo, el compilador Borland C++ de 32 bits ya ofrece el modificador opcional __int64.