tipos ¿Qué indica el estándar de C++ que indica el tamaño de int, el tipo largo?




unsigned int para que sirve (20)

El estándar de C ++ no especifica el tamaño de los tipos integrales en bytes, pero especifica rangos mínimos que deben ser capaces de mantener. Puede inferir el tamaño mínimo en bits desde el rango requerido. Puede deducir el tamaño mínimo en bytes a partir de eso y el valor de la macro CHAR_BIT que define el número de bits en un byte (en todas las plataformas menos oscuras, 8, y no puede ser menor que 8).

Una restricción adicional para char es que su tamaño es siempre de 1 byte, o bits CHAR_BIT (de ahí el nombre).

Los rangos mínimos requeridos por el estándar (página 22) son:

y rangos de tipo de datos en MSDN :

  1. signed char : -127 a 127 (nota, no -128 a 127; esto admite plataformas de signo y magnitud de complemento 1)
  2. unsigned char : 0 a 255
  3. char "normal": el mismo rango que el signed char o el unsigned char , implementation-defined
  4. signed short : -32767 a 32767
  5. unsigned short : 0 a 65535
  6. signed int : -32767 a 32767
  7. unsigned int : 0 a 65535
  8. signed long : -2147483647 a 2147483647
  9. unsigned long : 0 a 4294967295
  10. signed long long : -9223372036854775807 a 9223372036854775807
  11. unsigned long long : 0 a 18446744073709551615

Una implementación de C ++ (o C) puede definir el tamaño de un tipo en bytes tamaño de sizeof(type) a cualquier valor, siempre que

  1. la expresión sizeof(type) * CHAR_BIT evalúa a un número de bits lo suficientemente alto como para contener los rangos requeridos, y
  2. el orden del tipo sigue siendo válido (por ejemplo, sizeof(int) <= sizeof(long) ).

Los rangos reales específicos de la implementación se pueden encontrar en el encabezado <limits.h> en C, o <climits> en C ++ (o mejor aún, std::numeric_limits en el std::numeric_limits <limits> ).

Por ejemplo, así es como encontrarás el rango máximo para int :

DO:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++ :

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

Estoy buscando información detallada sobre el tamaño de los tipos básicos de C ++. Sé que depende de la arquitectura (16 bits, 32 bits, 64 bits) y el compilador.

Pero, ¿hay algún estándar para C ++?

Estoy usando Visual Studio 2008 en una arquitectura de 32 bits. Esto es lo que obtengo:

char  : 1 byte
short : 2 bytes
int   : 4 bytes
long  : 4 bytes
float : 4 bytes
double: 8 bytes

Intenté encontrar, sin mucho éxito, información confiable que indicara los tamaños de char , short , int , long , double , float (y otros tipos en los que no pensé) bajo diferentes arquitecturas y compiladores.


Si está interesado en una solución C ++ pura, hice uso de plantillas y solo el código estándar de C ++ para definir los tipos en tiempo de compilación en función de su tamaño de bit. Esto hace que la solución sea portátil entre compiladores.

La idea subyacente es muy simple: cree una lista que contenga los tipos char, int, short, long, long (versiones firmadas y no firmadas) y escanee la lista y, mediante el uso de la plantilla numeric_limits, seleccione el tipo con el tamaño dado.

Incluyendo este encabezado tienes 8 tipo stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

Si no se puede representar algún tipo, se evaluará como stdtype :: null_type también declarado en ese encabezado.

EL CÓDIGO A CONTINUACIÓN SE OFRECE SIN GARANTÍA, POR FAVOR, DOBLE CONSULTARLO.
También soy nuevo en METAPROGRAMMING, Siéntase libre de editar y corregir este código.
Probado con DevC ++ (así que una versión de gcc alrededor de 3.5)

#include <limits>

namespace stdtype
{
    using namespace std;


    /*
     * THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
     * YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS 
     * DECLARED/USED.
     *
     * PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
     */
    class null_type{};

    /*
     *  Template for creating lists of types
     *
     *  T is type to hold
     *  S is the next type_list<T,S> type
     *
     *  Example:
     *   Creating a list with type int and char: 
     *      typedef type_list<int, type_list<char> > test;
     *      test::value         //int
     *      test::next::value   //char
     */
    template <typename T, typename S> struct type_list
    {
        typedef T value;
        typedef S next;         

    };




    /*
     * Declaration of template struct for selecting a type from the list
     */
    template <typename list, int b, int ctl> struct select_type;


    /*
     * Find a type with specified "b" bit in list "list"
     *
     * 
     */
    template <typename list, int b> struct find_type
    {   
        private:
            //Handy name for the type at the head of the list
            typedef typename list::value cur_type;

            //Number of bits of the type at the head
            //CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
            enum {cur_type_bits = numeric_limits<cur_type>::digits};

        public:
            //Select the type at the head if b == cur_type_bits else
            //select_type call find_type with list::next
            typedef  typename select_type<list, b, cur_type_bits>::type type;
    };

    /*
     * This is the specialization for empty list, return the null_type
     * OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
     * (ie search for type with 17 bits on common archs)
     */
    template <int b> struct find_type<null_type, b>
    {   
        typedef null_type type;

    };


    /*
     * Primary template for selecting the type at the head of the list if
     * it matches the requested bits (b == ctl)
     *
     * If b == ctl the partial specified templated is evaluated so here we have
     * b != ctl. We call find_type on the next element of the list
     */
    template <typename list, int b, int ctl> struct select_type
    {   
            typedef  typename find_type<typename list::next, b>::type type; 
    };

    /*
     * This partial specified templated is used to select top type of a list
     * it is called by find_type with the list of value (consumed at each call)
     * the bits requested (b) and the current type (top type) length in bits
     *
     * We specialice the b == ctl case
     */
    template <typename list, int b> struct select_type<list, b, b>
    {
            typedef typename list::value type;
    };


    /*
     * These are the types list, to avoid possible ambiguity (some weird archs)
     * we kept signed and unsigned separated
     */

    #define UNSIGNED_TYPES type_list<unsigned char,         \
        type_list<unsigned short,                           \
        type_list<unsigned int,                             \
        type_list<unsigned long,                            \
        type_list<unsigned long long, null_type> > > > >

    #define SIGNED_TYPES type_list<signed char,         \
        type_list<signed short,                         \
        type_list<signed int,                           \
        type_list<signed long,                          \
        type_list<signed long long, null_type> > > > >



    /*
     * These are acutally typedef used in programs.
     * 
     * Nomenclature is [u]intN where u if present means unsigned, N is the 
     * number of bits in the integer
     *
     * find_type is used simply by giving first a type_list then the number of 
     * bits to search for.
     *
     * NB. Each type in the type list must had specified the template 
     * numeric_limits as it is used to compute the type len in (binary) digit.
     */
    typedef find_type<UNSIGNED_TYPES, 8>::type  uint8;
    typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
    typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
    typedef find_type<UNSIGNED_TYPES, 64>::type uint64;

    typedef find_type<SIGNED_TYPES, 7>::type    int8;
    typedef find_type<SIGNED_TYPES, 15>::type   int16;
    typedef find_type<SIGNED_TYPES, 31>::type   int32;
    typedef find_type<SIGNED_TYPES, 63>::type   int64;

}

Cuando se trata de tipos incorporados para diferentes arquitecturas y compiladores diferentes, simplemente ejecute el siguiente código en su arquitectura con su compilador para ver qué resultados produce. A continuación se muestra mi salida Ubuntu 13.04 (Raring Ringtail) de 64 bits g ++ 4.7.3. También tenga en cuenta lo que se respondió a continuación, por lo que la salida se ordena como tal:

"Hay cinco tipos de enteros con signo estándar: char con signo, int corto, int, int largo y int largo largo. En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que lo preceden en la lista".

#include <iostream>

int main ( int argc, char * argv[] )
{
  std::cout<< "size of char: " << sizeof (char) << std::endl;
  std::cout<< "size of short: " << sizeof (short) << std::endl;
  std::cout<< "size of int: " << sizeof (int) << std::endl;
  std::cout<< "size of long: " << sizeof (long) << std::endl;
  std::cout<< "size of long long: " << sizeof (long long) << std::endl;

  std::cout<< "size of float: " << sizeof (float) << std::endl;
  std::cout<< "size of double: " << sizeof (double) << std::endl;

  std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}


size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8

Para sistemas de 32 bits, el estándar 'de facto' es ILP32, es decir, int , long y puntero son todas las cantidades de 32 bits.

Para sistemas de 64 bits, el estándar primario de facto de Unix es LP64: long y puntero de 64 bits (pero int es de 32 bits). El estándar de Windows de 64 bits es LLP64 - long long y el puntero son de 64 bit (pero long e int son ambos de 32 bits).

Al mismo tiempo, algunos sistemas Unix utilizaban una organización ILP64.

Ninguna de estas normas de facto está legislada por la norma C (ISO / IEC 9899: 1999), pero todas están permitidas por ella.

Y, por definición, sizeof(char) es 1 , a pesar de la prueba en el script de configuración de Perl.

Tenga en cuenta que había máquinas (Crays) donde CHAR_BIT era mucho más grande que 8. Eso significaba, IIRC, que sizeof(int) también era 1, porque tanto char como int eran de 32 bits.


Se nos permite definir un sinónimo para el tipo para que podamos crear nuestro propio "estándar".

En una máquina en la que sizeof (int) == 4, podemos definir:

typedef int int32;

int32 i;
int32 j;
...

Entonces, cuando transferimos el código a una máquina diferente donde en realidad el tamaño de int largo es 4, podemos simplemente redefinir la ocurrencia individual de int.

typedef long int int32;

int32 i;
int32 j;
...

Puede utilizar variables proporcionadas por bibliotecas como OpenGL , Qt , etc.

Por ejemplo, Qt provides qint8 (se garantiza que es de 8 bits en todas las plataformas compatibles con Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, etc.


Como se mencionó el tamaño debe reflejar la arquitectura actual. Podrías tomar un pico en limits.h si quieres ver cómo maneja las cosas tu compilador actual.


Actualizado: C ++ 11 trajo los tipos de TR1 oficialmente al estándar:

  • long long int
  • sin firmar largo largo int

Y los tipos de "tamaño" de <cstdint>

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (y las contrapartes sin firmar).

Además usted obtiene:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Más las contrapartes sin firmar.

Estos tipos representan los tipos de enteros más pequeños con al menos el número especificado de bits. Del mismo modo, existen los tipos enteros "más rápidos" con al menos el número especificado de bits:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Más las versiones sin firmar.

Lo que "rápido" significa, en todo caso, depende de la implementación. Tampoco tiene que ser el más rápido para todos los propósitos.



Para los números de punto flotante hay un estándar (IEEE754) : los flotadores son de 32 bits y los dobles son 64. Este es un estándar de hardware, no un estándar de C ++, por lo que los compiladores teóricamente podrían definir flotante y doble a otro tamaño, pero en la práctica Nunca he visto una arquitectura que utilizara algo diferente.


unsigned char bits = sizeof(X) << 3;

donde X es un char , int , long , etc. le dará el tamaño de X en bits.


Hay cuatro tipos de enteros basados ​​en el tamaño:

  • entero corto: 2 bytes
  • entero largo: 4 bytes
  • long long integer: 8 byte
  • entero: depende del compilador (16 bits, 32 bits o 64 bits)

Puedes usar:

cout << "size of datatype = " << sizeof(datatype) << endl;

datatype = int , long int etc. Podrá ver el tamaño del tipo de datos que escriba.


Hay estándar.

El estándar C90 requiere que

sizeof(short) <= sizeof(int) <= sizeof(long)

El estándar C99 requiere que

sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

Aquí están las especificaciones C99 . Página 22 detalles de tamaños de diferentes tipos integrales.

Aquí está el tamaño de tipo int (bits) para plataformas Windows:

Type           C99 Minimum     Windows 32bit
char           8               8
short          16              16
int            16              32
long           32              32
long long      64              64

Si le preocupa la portabilidad, o si desea que el nombre del tipo refleje el tamaño, puede consultar el encabezado <inttypes.h> , donde están disponibles las siguientes macros:

int8_t
int16_t
int32_t
int64_t

Se garantiza que int8_t es de 8 bits, y que int16_t tiene una garantía de 16 bits, etc.


Me doy cuenta de que todas las demás respuestas aquí se han centrado casi exclusivamente en tipos integrales, mientras que el interrogador también preguntó sobre los puntos flotantes.

No creo que el estándar C ++ lo requiera, pero los compiladores para las plataformas más comunes en estos días generalmente siguen el estándar IEEE754 para sus números de punto flotante. Este estándar especifica cuatro tipos de punto flotante binario (así como algunos formatos BCD, que nunca he visto soporte en compiladores de C ++):

  • Media precisión (binario 16) - significando de 11 bits, rango de exponente -14 a 15
  • Precisión simple (binario 32): significado de 24 bits, rango de exponente -126 a 127
  • Doble precisión (binario 64) - significando de 53 bits, rango de exponente -1022 a 1023
  • Precisión cuádruple (binario128) - significando de 113 bits, rango de exponente -16382 a 16383

¿Cómo se relaciona esto con los tipos de C ++, entonces? Generalmente el float usa precisión simple; por lo tanto, sizeof(float) = 4 . Luego, el double utiliza la precisión doble (creo que esa es la fuente del nombre double ), y el long double puede ser la precisión doble o cuádruple (es cuádruple en mi sistema, pero en los sistemas de 32 bits puede ser doble). No conozco ningún compilador que ofrezca puntos flotantes de media precisión.

En resumen, este es el habitual:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 o 16

En una máquina de 64 bits:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8

El estándar de C ++ lo dice así:

3.9.1, §2:

Hay cinco tipos de enteros con signo: "char firmado", "int corto", "int", "int largo" y "int largo largo". En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que lo preceden en la lista. Las entradas simples tienen el tamaño natural sugerido por la arquitectura del entorno de ejecución (44); Los otros tipos de enteros con signo se proporcionan para satisfacer necesidades especiales.

(44) es decir, lo suficientemente grande como para contener cualquier valor en el rango de INT_MIN e INT_MAX, como se define en el encabezado <climits> .

La conclusión: depende de la arquitectura en la que estés trabajando. Cualquier otra suposición es falsa.


Como han respondido otros, los "estándares" dejan la mayoría de los detalles como "implementación definida" y solo establecen que el tipo "char" está al menos en "char_bis", y que "char <= short <= int <= long < = largo largo "(float y double son bastante consistentes con los estándares de punto flotante de IEEE, y el doble largo suele ser igual al doble, pero puede ser más grande en implementaciones más actuales).

Parte de las razones para no tener valores muy específicos y exactos es que los lenguajes como C / C ++ fueron diseñados para ser portátiles a una gran cantidad de plataformas de hardware, incluidos los sistemas informáticos en los que el tamaño de la palabra "char" puede ser de 4 bits o 7 bits, o incluso algún valor distinto de las computadoras "8/16- / 32- / 64-bit" a las que está expuesto el usuario promedio de computadoras domésticas. (El tamaño de palabra aquí significa la cantidad de bits de ancho en que normalmente funciona el sistema. Nuevamente, no siempre son de 8 bits como los usuarios de computadoras personales pueden esperar).

Si realmente necesita un objeto (en el sentido de una serie de bits que representan un valor integral) de un número específico de bits, la mayoría de los compiladores tienen algún método para especificar eso; Pero generalmente no es portátil, incluso entre compiladores hechos por la compañía de ame pero para diferentes plataformas. Algunos estándares y prácticas (especialmente limitan.h y similares) son lo suficientemente comunes como para que la mayoría de los compiladores tengan soporte para determinar el tipo de ajuste óptimo para un rango específico de valores, pero no el número de bits utilizados. (Es decir, si sabe que necesita mantener valores entre 0 y 127, puede determinar que su compilador soporta un tipo "int8" de 8 bits que será lo suficientemente grande como para mantener el rango completo deseado, pero no algo como un tipo "int7" que sería una coincidencia exacta para 7 bits.)

Nota: muchos paquetes fuente * Un * x utilizaron el script "./configure" que probará las capacidades del compilador / sistema y generará un Makefile y config.h adecuados. Puede examinar algunos de estos scripts para ver cómo funcionan y cómo prueban las capacidades del comiler / sistema, y ​​seguir su ejemplo.


No, no hay estándar para los tamaños de tipo. Estándar solo requiere que:

sizeof(short int) <= sizeof(int) <= sizeof(long int)

Lo mejor que puedes hacer si quieres variables de un tamaño fijo es usar macros como esta:

#ifdef SYSTEM_X
  #define WORD int
#else
  #define WORD long int
#endif

Luego puedes usar WORD para definir tus variables. No es que me guste esto pero es la forma más portátil .


Si necesita tipos de tamaño fijo, use tipos como uint32_t (entero sin signo de 32 bits) definidos en stdint.h . Se especifican en C99 .







c++-faq