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

696

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

He intentado encontrar, sin mucho éxito, la información fiable según los tamaños de char, short, int, long, double, float(y otros tipos que no pensaron) en diferentes arquitecturas y compiladores.

Jérôme
fuente
18
@thyrgle no es por elección ... hay tantas arquitecturas para soportar que necesita ser flexible.
Krakkos
44
¿Por qué no se eliminan todos los tipos vagos, y estandarizar todo a tipos definidos longitud de bits por ejemplo int32_t, uint32_t, etc. int64_t
developerbmw
55
@thyrgle En realidad, es bastante difícil estandarizar algo como esto. A diferencia de Java, donde estas cosas son constantes debido a la forma en que funciona la JVM, C / C ++ esencialmente tiene que adherirse al sistema en el que se ejecutan sin ninguna capa de abstracción elegante (al menos no tantas como con Java) Entre. Si el tamaño de la int es tan importante, se puede usar int16_t, int32_ty int64_t(necesito iostreamincluirlo si no recuerdo mal). Lo bueno de esto es que int64_t no debería tener problemas en un sistema de 32 bits (aunque esto afectará el rendimiento).
rbaleksandar
55
@rbaleksandar En realidad están definidos en <cstdint>, no <iostream>.
Justin Time - Restablece a Monica

Respuestas:

685

El estándar C ++ no especifica el tamaño de los tipos integrales en bytes, pero especifica los rangos mínimos que deben poder contener. Puede inferir el tamaño mínimo en bits del rango requerido. Puede inferir el tamaño mínimo en bytes a partir de eso y el valor de la CHAR_BITmacro que define el número de bits en un byte . En todas las plataformas, excepto en las más oscuras, es 8, y no puede ser menor que 8. Esto se debe a que debe ser lo suficientemente grande como para contener "las unidades de código de ocho bits de la forma de codificación Unicode UTF-8".

Una restricción adicional para chares que su tamaño es siempre de 1 byte o CHAR_BITbits (de ahí el nombre). Esto se establece explícitamente en la norma.

El estándar C es una referencia normativa para el estándar C ++, por lo que aunque no establece estos requisitos explícitamente, C ++ requiere los rangos mínimos requeridos por el estándar C (página 22), que son los mismos que los de los rangos de tipo de datos en MSDN :

  1. signed char: -127 a 127 (nota, no -128 a 127; esto se adapta a plataformas de complemento y signo y magnitud de 1)
  2. unsigned char: 0 a 255
  3. "simple" char: mismo rango que signed charo unsigned char, definido por la implementación
  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 sizeof(type)a cualquier valor, siempre que

  1. la expresión se sizeof(type) * CHAR_BITevalúa en un número de bits lo suficientemente alto como para contener los rangos requeridos, y
  2. la ordenación del tipo sigue siendo válida (p sizeof(int) <= sizeof(long). ej .).

Al unir todo esto, tenemos la garantía de que:

  • char, signed chary unsigned charson al menos 8 bits
  • signed short, unsigned short, signed int, Y unsigned intson al menos 16 bits
  • signed longy unsigned longson al menos 32 bits
  • signed long longy unsigned long longson al menos 64 bits

No se ofrece ninguna garantía sobre el tamaño de, floato doubleexcepto, que doubleproporcione al menos tanta precisión como float.

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

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

C:

#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();
Alex B
fuente
49
Más bien, el estándar C ++ usa la palabra byte para significar "1 char", y no el significado habitual.
Ben Voigt
44
@Programador Lea la respuesta (nota del punto 1 entre paréntesis), o la redacción del estándar real (vinculado en la respuesta). El estándar C acomoda arquitecturas de complemento de 1, que tienen una representación diferente del complemento de 2 más extendido. Los rangos mínimos garantizados casi siempre diferirán de los rangos reales que proporciona una implementación.
Alex B
99
@Alex B no mencionaste nada sobre el doble en tu respuesta. ¿Puede actualizar su respuesta para las variables de punto flotante?
Cool_Coder
3
@Cool_Coder: el punto flotante es un hervidor adicional de pescado, que duplica fácilmente el tamaño de las publicaciones.
Deduplicador
3
@Mooing Duck: "toda versión de C ++ requería 256 valores distintos [para los tipos de caracteres firmados]" No, eso no era cierto hasta que se solucionó en las especificaciones más recientes de C ++. Las especificaciones más antiguas permitían que los tipos de caracteres con signo tuvieran patrones de bits que no se asignaban a un número, por lo que no cumplían el requisito de que hubiera 256 valores distintos. "Para los tipos de caracteres sin signo, todos los patrones de bits posibles de la representación del valor representan números. Estos requisitos no se cumplen para otros tipos".
Adrian McCarthy
241

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

Para los sistemas de 64 bits, el estándar principal de facto de Unix es LP64, longy el puntero es de 64 bits (pero intes de 32 bits). El estándar de Windows de 64 bits es LLP64 - long longy el puntero de 64 bits (pero longy intson ambos de 32 bits).

Hubo un tiempo en que algunos sistemas Unix usaban una organización ILP64.

Ninguno de estos estándares de facto está legislado por el estándar C (ISO / IEC 9899: 1999), pero todos están permitidos por él.

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_BITera mucho mayor que 8. Eso significa, IIRC, que sizeof(int)también fue 1, debido a que tanto chary interan de 32 bits.

Jonathan Leffler
fuente
73
+1 por indicar cómo son realmente las cosas en los casos que más le importan, en lugar de cómo son las cosas en teoría. Si quieres 32bit usa int, si quieres 64bit usa largo largo. Si quieres nativo usa size_t. Evite el tiempo "simple" porque varía. Eso debería funcionar para la mayoría de las aplicaciones.
Eloff
37
+1 por la respuesta. @Eloff: por el contrario ... si desea un uso de 32 bits [u]int32_to similar, si desea un uso de 64 bits [u]int64_t... si no tiene un encabezado para ellos, descargue o haga uno, preferiblemente con la selección de tiempo de compilación de tales tipos o aserciones estáticas para verificar el tamaño. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Si los tamaños precisos no son tan importantes y solo le importa que sean al menos tan grandes, entonces su consejo es válido para las plataformas modernas comunes de PC / servidor.
Tony Delroy
8
Tenga en cuenta que no solo las máquinas de crayolas antiguas tienen CHAR_BIT> 8. por ejemplo, los DSP a menudo tienen CHAR_BIT de 16 o 32. (vea, por ejemplo, estos )
nos
2
@nos: Gracias por el enlace. Es muy útil tener sistemas modernos y actuales identificados para los casos extraños. Por curiosidad, ¿cuál es el código establecido en esas máquinas? Si el conjunto de códigos es UTF-16, entonces 0xFFFF no es un carácter válido, y si el conjunto de códigos es un conjunto de códigos ISO 8859-x, nuevamente 0xFFFF no es un carácter válido (los códigos de caracteres de 0x00 a 0xFF son válidos). Todavía no estoy convencido de que haya un problema al detectar EOF, pero ciertamente hay margen de precaución, y probablemente para escribir y usar una función int get_char(FILE *fp, char *c)que devuelve EOF o 0 y establece *c.
Jonathan Leffler
2
@joelw: C11 requiere que, dado uint32_t x=1,y=2;el valor dex-y debe ser 4294967295 en plataformas donde "int" es 32 bits o menor, y -1 en plataformas donde "int" es 33 bits o mayor. Además, requiere que x*yse evalúe usando aritmética modular para todos los valores de x e y si "int" es 32 bits o más pequeño, y la aritmética convencional si es de 65 bits o más, pero no establece ningún requisito sobre lo que puede suceder con valores grandes de x e y si "int" es de 33 a 64 bits.
supercat
88

En la práctica no existe tal cosa. A menudo puede esperar std::size_trepresentar el tamaño entero nativo sin signo en la arquitectura actual. es decir, 16 bits, 32 bits o 64 bits, pero no siempre es el caso como se señala en los comentarios a esta respuesta.

En cuanto a todos los demás tipos incorporados, realmente depende del compilador. Aquí hay dos extractos del borrador actual del último estándar de C ++:

Hay cinco tipos enteros con signo estándar: char firmado, short int, int, long int y long long int. En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que le preceden en la lista.

Para cada uno de los tipos de enteros con signo estándar, existe un tipo de entero sin signo estándar correspondiente (pero diferente): unsigned char, unsigned short int, unsigned int, unsigned long int y unsigned long long int, cada uno de los cuales ocupa la misma cantidad de almacenamiento y tiene los mismos requisitos de alineación.

Si lo desea, puede afirmar estáticamente (tiempo de compilación) el tamaño de estos tipos fundamentales. Alertará a las personas a pensar en portar su código si cambia el tamaño de las suposiciones.

John Leidegren
fuente
77
buen post. Otra cosa que se requiere son los siguientes tamaños de bits mínimos (documentados en c89 / c99 junto con los límites.h y asumidos por c ++): char> = 8, short e int> = 16, long> = 32.
Johannes Schaub - litb
1
Además, en una plataforma AVR de 8 bits, size_t no será de 8 bits, sino 16, porque los tamaños de puntero e int son de 16 bits. Por lo tanto, el tamaño de datos nativo del procesador no está relacionado con size_t.
Robotbugs
80

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 . La página 22 detalla los tamaños de los diferentes tipos integrales.

Aquí están los tamaños 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 desea que el nombre del tipo refleje el tamaño, puede mirar el encabezado <inttypes.h>, donde están disponibles las siguientes macros:

int8_t
int16_t
int32_t
int64_t

int8_ttiene una garantía de 8 bits y int16_t16 bits, etc.

yinyueyouge
fuente
8
Nitpick menor: ¿dónde dice el estándar sizeof(long) < sizeof(long long)en lugar del simétrico sizeof(long) <= sizeof(long long)?
Jonathan Leffler
2
@JonathonLeffler - ver C99 5.2.4.2.1 - Tamaños de tipos enteros. minsizeof (int) == 16 bits, minsizeof (largo) == 32 bits, minsizeof (largo largo) == 64 bits. Así que creo que tiene razón en el <= ya que no se especifica maxsizeof (type).
Jesse Chisholm
Del mismo modo sizeof (float) <= sizeof (double) <= sizeof (long double). De acuerdo con C99 7.12 párrafo 2.
Jesse Chisholm
38

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 .

Ben
fuente
10
Se especifican pero no se requieren.
dreamlax
2
@dreamlax ¿Qué plataformas no lo incluyen?
Levi Morrison
3
@LeviMorrison: cualquier plataforma que no los tenga en la forma requerida. Una plataforma que tiene CHAR_BIT == 16, por ejemplo, no tendrá int8_t. Cualquier plataforma que no use el complemento de dos no tendrá ninguno de ellos (ya que el estándar requiere el complemento de dos).
DevSolar
36

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

  • largo largo int
  • unsigned long long int

Y los tipos "dimensionados" de <cstdint>

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

Además obtienes:

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

Estos tipos representan los tipos 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
  • Además de las versiones sin firmar.

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

Brian Neal
fuente
Esto es parte del estándar C ++ 11 ahora.
Jaan
2
"rápido" solo significa adaptado a la arquitectura de hardware. Si los registros son de 16 bits, entonces int_fast8_t es un valor de 16 bits. Si los registros son de 32 bits, int_fast8_t e int_fast16_t son valores de 32 bits. etc. Ver C99 sección 7.18.1.3 párrafo 2.
Jesse Chisholm
19

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

3.9.1, §2:

Hay cinco tipos 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 le 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 firmados 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é trabajando. Cualquier otra suposición es falsa.

Jérôme Radix
fuente
12

No, no hay un estándar para los tamaños de letra. El estándar solo requiere que:

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

Lo mejor que puede hacer si desea variables de un tamaño fijo es usar macros como este:

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

Luego puede usar WORD para definir sus variables. No es que me guste, pero es la forma más portátil .

Emiliano
fuente
44
El problema es que WORD se distribuye alrededor del programa en áreas que no dependen realmente de un tamaño fijo (mira algunos códigos de Windows). Como descubrí al pasar de un sistema de 16 bits a un sistema de 32 bits, termina con el mismo problema que WORD estaba destinado a resolver.
lilburne
@liburne Por supuesto, debe usar WORD solo cuando necesite una variable de tamaño fijo, como cuando está leyendo / escribiendo desde / a un archivo. Si un fragmento de código no depende realmente de un tamaño fijo, entonces debe usar variables "int" normales.
Emiliano
3
Lo mejor que puede hacer para obtener tamaños portátiles debe ser#include <boost/cstdint.hpp>
kizzx2
11

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 redefinir la ocurrencia única de int.

typedef long int int32;

int32 i;
int32 j;
...
milán-j
fuente
1
Eso no es necesario dado el encabezado estándar <stdint.h>(C99 y posterior, y cualquiera que sea el estándar C ++ adoptó la versión C99 de la biblioteca C).
Keith Thompson
8

Para los números de coma flotante hay un estándar (IEEE754) : los flotantes 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 duplicar a otro tamaño, pero en la práctica I ' Nunca he visto una arquitectura que usara algo diferente.

Crashworks
fuente
2
Sin embargo, el cumplimiento con IEEE 754 (también conocido como IEC 559) es opcional dentro de C ++ (probablemente también C, pero no estoy seguro). Ver std :: numeric_limits :: is_iec559.
Drew Hall
1
Entonces no ha visto el compilador de TI para DSP TMS320C28xx, donde doubletiene el mismo tamaño que float(y intel mismo que charambos son de 16 bits). Pero tienen un 64 bit long double.
Starblue
7

Existe un estándar y se especifica en los diversos documentos de estándares (ISO, ANSI y demás).

Wikipedia tiene una gran página que explica los diversos tipos y el máximo que pueden almacenar: Integer in Computer Science.

Sin embargo, incluso con un compilador estándar de C ++, puede averiguarlo con relativa facilidad utilizando el siguiente fragmento de código:

#include <iostream>
#include <limits>


int main() {
    // Change the template parameter to the various different types.
    std::cout << std::numeric_limits<int>::max() << std::endl;
}

La documentación para std :: numeric_limits se puede encontrar en Roguewave . Incluye una gran cantidad de otros comandos a los que puede llamar para conocer los diversos límites. Esto se puede usar con cualquier tipo arbitrario que transmita tamaño, por ejemplo std :: streamsize.

La respuesta de John contiene la mejor descripción, ya que están garantizadas. No importa en qué plataforma se encuentre, hay otra buena página que detalla cuántos bits DEBE contener cada tipo: tipos int , que se definen en el estándar.

¡Espero que esto ayude!

X-Istence
fuente
7

Puedes usar:

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

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

Población Xplosiva
fuente
7

Cuando se trata de tipos incorporados para diferentes arquitecturas y diferentes compiladores, simplemente ejecute el siguiente código en su arquitectura con su compilador para ver qué produce. A continuación se muestra mi Ubuntu 13.04 salida (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 enteros con signo estándar: char con signo, int corto, int, largo int y largo largo int. En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que le 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
bjackfly
fuente
sizeof(char)No debe ser incluido.
Ven
3

Como se mencionó, el tamaño debe reflejar la arquitectura actual. Podrías echar un limits.hvistazo si quieres ver cómo tu compilador actual está manejando las cosas.

John T
fuente
Gracias, pero me gustaría saber los tamaños de las arquitecturas que no tengo myselft (como 64 bits). Este tutorial solo habla sobre las arquitecturas de 32 bits ...
Jérôme
2

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

Parte de las razones para no tener valores muy específicos y exactos se debe a que los lenguajes como C / C ++ fueron diseñados para ser portátiles en una gran cantidad de plataformas de hardware, incluidos los sistemas informáticos en los que el tamaño de 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. (Tamaño de palabra aquí, lo que significa cuántos bits de ancho funciona normalmente el sistema; de nuevo, no siempre es de 8 bits como pueden esperar los usuarios de computadoras domésticas).

Si realmente necesita un objeto (en el sentido de una serie de bits que represente un valor integral) de un número específico de bits, la mayoría de los compiladores tienen algún método para especificarlo; Pero generalmente no es portátil, incluso entre compiladores hechos por la compañía ame, sino para diferentes plataformas. Algunos estándares y prácticas (especialmente los límites. H y similares) son lo suficientemente comunes como para que la mayoría de los compiladores tengan soporte para determinar en el tipo de mejor ajuste 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 admite un tipo "int8" de 8 bits que será lo suficientemente grande como para contener el rango completo deseado, pero no algo así 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 sistema / comiler, y seguir su ejemplo.

CM
fuente
1

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

La idea detrás es muy simple: cree una lista que contenga tipos char, int, short, long, long long (versiones con y sin signo) 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 tipos stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

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

EL CÓDIGO A CONTINUACIÓN SE OTORGA SIN GARANTÍA, POR FAVOR REVISE DOBLE.
SOY NUEVO EN METAPROGRAMMING TAMBIÉN, NO DEBE EDITAR Y CORREGIR ESTE CÓDIGO.
Probado con DevC ++ (por lo 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;

}
usuario781847
fuente
0
unsigned char bits = sizeof(X) << 3;

donde Xestá una char, int, longetc .. le dará tamaño de Xen bits.

usuario3154672
fuente
1
un carácter no siempre es de 8 bits, por lo que su expresión no funcionará en arquitecturas con caracteres que no sean de 8 bits . Solo se sizeof(type)*CHAR_BITmantiene
phuclv
Incluso si CHAR_BITse garantizara que fueran 8 bits, << 3es simplemente una forma ofuscada de escribir * 8o * CHAR_BIT.
Keith Thompson,
0

De Alex B El estándar C ++ no especifica el tamaño de los tipos integrales en bytes, pero especifica los rangos mínimos que deben poder contener. Puede inferir el tamaño mínimo en bits del rango requerido. Puede inferir 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 es 8, y no puede ser inferior a 8).

Una restricción adicional para char es que su tamaño siempre es 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:

char firmado: -127 a 127 (nota, no -128 a 127; esto acomoda plataformas de complemento de 1) char sin firmar: 0 a 255 char "normal": -127 a 127 o 0 a 255 (depende de la firma de char predeterminada) firmado corto: -32767 a 32767 sin signo corto: 0 a 65535 con signo int: -32767 a 32767 sin signo int: 0 a 65535 con signo largo: -2147483647 a 2147483647 sin signo largo: 0 a 4294967295 con signo largo largo: -9223372036854775807 a 9223372036854775807 sin signo largo 0 a 18446744073709551615 Una implementación de C ++ (o C) puede definir el tamaño de un tipo en bytes sizeof (type) a cualquier valor, siempre que

la expresión sizeof (type) * CHAR_BIT evalúa el número de bits suficiente para contener los rangos requeridos, y el orden del tipo sigue siendo válido (por ejemplo, sizeof (int) <= sizeof (long)). Los rangos específicos de implementación reales se pueden encontrar en el encabezado en C, o en C ++ (o incluso mejor, std :: numeric_limits en el encabezado).

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

C:

#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();

Esto es correcto, sin embargo, también tenía razón al decir que: char: 1 byte corto: 2 bytes int: 4 bytes de largo: 4 bytes flotante: 4 bytes doble: 8 bytes

Debido a que las arquitecturas de 32 bits siguen siendo las predeterminadas y más utilizadas, y han mantenido estos tamaños estándar desde los días anteriores a 32 bits cuando la memoria estaba menos disponible, y para la compatibilidad y estandarización hacia atrás permaneció igual. Incluso los sistemas de 64 bits tienden a usar estos y tienen extensiones / modificaciones. Consulte esto para obtener más información:

http://en.cppreference.com/w/cpp/language/types

JCoder
fuente
0

Noté que todas las otras 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, para los cuales nunca he visto soporte en compiladores C ++):

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

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

En resumen, esto es lo habitual:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 o 16
Celticminstrel
fuente
Es curioso que llegué a esta pregunta como parte de preguntarme por qué Jeff usa más bytes de los que necesita.
Aniruddha Varma
-2

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

Por ejemplo, Qt proporciona qint8 (con garantía de 8 bits en todas las plataformas compatibles con Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, etc.

Ley y
fuente
1
No responde la pregunta
EvilTeach
-8

En una máquina de 64 bits:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8
usuario2826084
fuente
2
En algunas máquinas de 64 bits intes de 8 bytes, pero el otro no está garantizado. No hay nada que diga que chardebería ser solo 8 bits. Está permitido tenerlo sizeof(void*)==4aunque sea de 64 bits.
Skyking
-10

Hay cuatro tipos de enteros según el tamaño:

  • entero corto: 2 bytes
  • entero largo: 4 bytes
  • entero largo largo: 8 bytes
  • entero: depende del compilador (16 bits, 32 bits o 64 bits)
ricky
fuente
11
Falso, todos dependen de la arquitectura, con los rangos mínimos descritos en una de las otras respuestas. Nada detiene una implementación short, inty longtodos los enteros de 32 bits.
Matteo Italia
Ni siquiera has usado los nombres correctos para los tipos. Los nombres usan la palabra clave int, no la palabra "entero".
Keith Thompson,