O que o padrão C ++ indica o tamanho do tipo int, long?

696

Estou procurando informações detalhadas sobre o tamanho dos tipos básicos de C ++. Eu sei que isso depende da arquitetura (16 bits, 32 bits, 64 bits) e do compilador.

Mas existem padrões para C ++?

Estou usando o Visual Studio 2008 em uma arquitetura de 32 bits. Aqui está o que eu recebo:

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

Tentei encontrar, sem muito sucesso, informações confiáveis indicando os tamanhos de char, short, int, long, double, float(e outros tipos eu não pensar) sob diferentes arquiteturas e compiladores.

Jérôme
fonte
18
@thyrgle não é por escolha ... existem tantas arquiteturas para oferecer suporte que precisam ser flexíveis.
Krakkos
4
Por que eles não remover todos os tipos de vagas, e padronizar tudo para tipos de comprimento bit definidas por exemplo int32_t, uint32_t, int64_t etc.
developerbmw
5
@thyrgle Na verdade, é muito difícil padronizar algo assim. Diferentemente do Java, onde essas coisas são constantes devido à maneira como a JVM funciona, o C / C ++ basicamente precisa se ater ao sistema em que é executado, sem nenhuma camada de abstração extravagante (pelo menos não tantas como no Java). entre. Se o tamanho do int é que um importante pode usar int16_t, int32_te int64_t(é necessário o iostreamincluem, por que, se bem me lembro). O que é interessante sobre isso é que o int64_t não deve ter problemas em um sistema de 32 bits (isso afetará o desempenho).
Rbaleksandar
5
@rbaleksandar Eles estão realmente definidos <cstdint>, não <iostream>.
Justin Time - Restabelece Monica

Respostas:

685

O padrão C ++ não especifica o tamanho dos tipos integrais em bytes, mas especifica os intervalos mínimos que eles devem poder manter. Você pode inferir o tamanho mínimo em bits do intervalo necessário. Você pode inferir o tamanho mínimo em bytes disso e o valor da CHAR_BITmacro que define o número de bits em um byte . Em todas as plataformas, exceto as mais obscuras, é 8 e não pode ser inferior a 8. Isso porque deve ser grande o suficiente para conter "as unidades de código de oito bits do formulário de codificação Unicode UTF-8".

Uma restrição adicional charé que seu tamanho é sempre 1 byte ou CHAR_BITbits (daí o nome). Isto é afirmado explicitamente no padrão.

O padrão C é uma referência normativa para o padrão C ++, portanto, mesmo que não indique esses requisitos explicitamente, o C ++ exige os intervalos mínimos exigidos pelo padrão C (página 22), que são os mesmos que os do Tipo de dados no MSDN :

  1. signed char: -127 a 127 (observe, não -128 a 127; isso acomoda plataformas de complemento de 1 e sinal e magnitude)
  2. unsigned char: 0 a 255
  3. "plain" char: mesmo intervalo que signed charou unsigned char, definido pela implementação
  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

Uma implementação C ++ (ou C) pode definir o tamanho de um tipo em bytes sizeof(type)para qualquer valor, desde que

  1. a expressão é sizeof(type) * CHAR_BITavaliada para um número de bits alto o suficiente para conter os intervalos necessários e
  2. a ordem do tipo ainda é válida (por exemplo sizeof(int) <= sizeof(long)).

Juntando tudo isso, temos a garantia de que:

  • char,, signed chare unsigned charsão pelo menos 8 bits
  • signed short, unsigned short, signed int, E unsigned intsão pelo menos 16 bits
  • signed longe unsigned longtem pelo menos 32 bits
  • signed long longe unsigned long longtem pelo menos 64 bits

Nenhuma garantia é feita sobre o tamanho floatou a doubleexceção que doublefornece pelo menos a mesma precisão que float.

Os intervalos reais específicos da implementação podem ser encontrados no <limits.h>cabeçalho em C ou <climits>em C ++ (ou, melhor ainda, std::numeric_limitsem modelos no <limits>cabeçalho).

Por exemplo, é assim que você encontrará o alcance 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
fonte
49
Em vez disso, o padrão C ++ usa a palavra byte para significar "1 char", e não o significado usual.
Ben Voigt
4
@ Programador Leia a resposta (observação do ponto 1 entre parênteses) ou a redação do padrão real (vinculada na resposta). O padrão C acomoda arquiteturas de complemento de 1, que têm representação diferente do complemento de 2 mais difundido. Os intervalos mínimos garantidos quase sempre diferem dos intervalos reais fornecidos por uma implementação.
Alex B
9
@ Alex B, você não mencionou nada sobre o dobro na sua resposta. Você pode atualizar sua resposta para variáveis ​​de ponto flutuante?
precisa saber é o seguinte
3
@Cool_Coder: O ponto flutuante é uma chaleira adicional de peixe, dobrando facilmente o tamanho dos postes.
Deduplicator
3
@Mooing Duck: "todas as versões do C ++ exigiam 256 valores distintos [para tipos de caracteres assinados]" Não, isso não era verdade até que fosse corrigido nas especificações mais recentes do C ++. As especificações mais antigas permitiam que os tipos de caracteres assinados tivessem padrões de bits que não são mapeados para um número; portanto, estavam faltando o requisito de haver 256 valores distintos. "Para tipos de caracteres não assinados, todos os padrões de bits possíveis da representação de valor representam números. Esses requisitos não são válidos para outros tipos."
Adrian McCarthy
241

Para sistemas de 32 bits, o padrão 'de facto' é ILP32 - ou seja, int, longe ponteiro são todas as quantidades de 32 bits.

Para sistemas de 64 bits, o principal padrão de fato do Unix é o LP64 - longe o ponteiro é de 64 bits (mas inté de 32 bits). O padrão de 64-bit Windows é LLP64 - long longe ponteiro são de 64 bits (mas longe intsão ambas de 32 bits).

Ao mesmo tempo, alguns sistemas Unix usavam uma organização ILP64.

Nenhum desses padrões de fato é legislado pelo padrão C (ISO / IEC 9899: 1999), mas todos são permitidos por ele.

E, por definição, sizeof(char)é 1, apesar do teste no script de configuração do Perl.

Observe que havia máquinas (Crays) CHAR_BITmuito maiores que 8. Isso significava, IIRC, quesizeof(int) também era 1, porque ambos chare interam de 32 bits.

Jonathan Leffler
fonte
73
+1 por indicar como as coisas realmente são nos casos mais importantes, em vez de como são as teorias. Se você deseja 32 bits, use int, se você quiser 64 bits, use muito tempo. Se você quiser usar nativo size_t. Evite "simples" por muito tempo, pois varia. Isso deve funcionar para a maioria dos aplicativos.
Eloff
37
+1 para a resposta. @Eloff: pelo contrário ... se você quiser usar 32 bits [u]int32_tou similar, se quiser usar 64 bits [u]int64_t... se não tiver um cabeçalho para eles, faça o download ou crie um, de preferência com a seleção do tempo de compilação de tipos ou asserções estáticas para verificar o tamanho. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Se os tamanhos precisos não são tão importantes e você se importa apenas com o tamanho, é aconselhável seguir as plataformas modernas de PC / servidor.
Tony Delroy
8
Note que não é máquinas Cray apenas velhos que têm CHAR_BIT> 8. por exemplo DSPs muitas vezes têm CHAR_BIT de 16 ou 32. (ver, por exemplo estes )
nºs
2
@nos: Obrigado pelo link. É muito útil ter sistemas modernos e atuais identificados para os casos excêntricos. Por curiosidade, qual é o código definido nessas máquinas? Se o conjunto de códigos for UTF-16, 0xFFFF não é um caractere válido e se o conjunto de códigos for um conjunto de códigos ISO 8859-x, novamente 0xFFFF não será um caractere válido (códigos de caracteres de 0x00 a 0xFF são válidos). Ainda não estou convencido de que haja um problema ao detectar o EOF, mas certamente há espaço para cautela e, provavelmente, para escrever e usar uma função int get_char(FILE *fp, char *c)que retorna EOF ou 0 e define *c.
Jonathan Leffler
2
@joelw: C11 exige que, dado uint32_t x=1,y=2;o valor de, x-ydeva ser 4294967295 em plataformas onde "int" seja 32 bits ou menor, e -1 em plataformas em que "int" seja 33 bits ou maior. Além disso, requer que x*yseja avaliado usando aritmética modular para todos os valores de x e y se "int" for 32 bits ou menor e aritmética convencional se 65 bits ou maior, mas não impõe nenhum requisito sobre o que pode acontecer com valores grandes de x e y se "int" for de 33 a 64 bits.
Supercat 6/16
88

Na prática, não existe tal coisa. Freqüentemente, você pode esperar std::size_trepresentar o tamanho inteiro nativo não assinado na arquitetura atual. ou seja, 16 bits, 32 bits ou 64 bits, mas nem sempre é o caso, conforme indicado nos comentários a esta resposta.

No que diz respeito a todos os outros tipos internos, isso realmente depende do compilador. Aqui estão dois trechos retirados do rascunho atual do último padrão C ++:

Existem cinco tipos de número inteiro com sinal padrão: char assinado, int curto, int, long int e long long int. Nesta lista, cada tipo fornece pelo menos a quantidade de armazenamento que os anteriores à lista.

Para cada um dos tipos de números inteiros assinados padrão, existe um tipo de número inteiro não assinado padrão correspondente (mas diferente): char não assinado, int curto não assinado, int não assinado, int não assinado, int longo não assinado e int longo longo não assinado, cada um dos quais ocupa a mesma quantidade de armazenamento e possui os mesmos requisitos de alinhamento.

Se você quiser, pode estaticamente (em tempo de compilação) afirmar o tamanho desses tipos fundamentais. Ele alertará as pessoas a pensar em portar seu código se o tamanho das suposições mudar.

John Leidegren
fonte
7
bom post. outra coisa necessária é o seguinte tamanho mínimo de bits (documentado em c89 / c99 junto com limits.he assumido por c ++): char> = 8, short e int> = 16, long> = 32.
Johannes Schaub - litb 26/02/09
1
Além disso, em uma plataforma AVR de 8 bits, size_t não será de 8 bits, mas 16, porque os tamanhos de ponteiro e int são de 16 bits. Portanto, o tamanho dos dados nativos do processador não está relacionado ao size_t.
Robotbugs
80

Existe padrão.

O padrão C90 exige que

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

O padrão C99 exige que

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

Aqui estão as especificações do C99 . A página 22 detalha tamanhos de diferentes tipos integrais.

Aqui estão os tamanhos do 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

Se você está preocupado com a portabilidade ou deseja que o nome do tipo reflita o tamanho, consulte o cabeçalho <inttypes.h>, onde estão disponíveis as seguintes macros:

int8_t
int16_t
int32_t
int64_t

int8_ttem 8 bits e int16_t16 bits, etc.

yinyueyouge
fonte
8
Nitpick menor: onde o padrão diz sizeof(long) < sizeof(long long)em oposição ao simétrico sizeof(long) <= sizeof(long long)?
27613 Jonathan Leffler
2
@ JonathonLeffler - consulte C99 5.2.4.2.1 - Tamanhos de tipos inteiros. minsizeof (int) == 16 bits, minsizeof (long) == 32 bits, minsizeof (long long) == 64 bits. Então eu acho que você está certo no <= como nenhum maxsizeof (type) é especificado.
Jesse Chisholm
Da mesma forma sizeof (float) <= sizeof (double) <= sizeof (long double). De acordo com o C99 7.12, parágrafo 2.
Jesse Chisholm
38

Se você precisar de tipos de tamanho fixo, use tipos como uint32_t (número inteiro não assinado de 32 bits) definido em stdint.h . Eles são especificados em C99 .

Ben
fonte
10
Eles são especificados, mas não são necessários.
dreamlax
2
@dreamlax Que plataformas não o incluem?
Levi Morrison
3
@ LeviMorrison: qualquer plataforma que não os possua no formato exigido. Uma plataforma que possui CHAR_BIT == 16, por exemplo, não possui int8_t. Qualquer plataforma que não use o complemento de dois não terá nenhum deles (como o complemento de dois é exigido pelo padrão).
DevSolar 16/07/19
36

Atualizado: o C ++ 11 trouxe os tipos do TR1 oficialmente para o padrão:

  • long long int
  • não assinado long long int

E os tipos "dimensionados" de <cstdint>

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (e as contrapartes não assinadas).

Além disso, você obtém:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Além das contrapartes não assinadas.

Esses tipos representam os menores números inteiros com pelo menos o número especificado de bits. Da mesma forma, existem os tipos inteiros "mais rápidos" com pelo menos o número especificado de bits:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Além das versões não assinadas.

O que significa "rápido", se é que existe alguma coisa, depende da implementação. Também não precisa ser o mais rápido para todos os fins.

Brian Neal
fonte
Isso faz parte do padrão C ++ 11 agora.
27414 Jaan
2
"rápido" significa apenas adaptado à arquitetura de hardware. Se os registradores forem de 16 bits, int_fast8_t é um valor de 16 bits. Se os registros forem de 32 bits, int_fast8_t e int_fast16_t são ambos valores de 32 bits. etc. Consulte a seção 7.18.1.3 da C99, parágrafo 2.
Jesse Chisholm
19

O padrão C ++ diz assim:

3.9.1, §2:

Existem cinco tipos de números inteiros assinados: "caractere assinado", "int curto", "int", "int longo" e "int longo longo". Nesta lista, cada tipo fornece pelo menos a quantidade de armazenamento que os anteriores à lista. Ints simples têm o tamanho natural sugerido pela arquitetura do ambiente de execução (44); os outros tipos de números inteiros assinados são fornecidos para atender a necessidades especiais.

(44), ou seja, grande o suficiente para conter qualquer valor no intervalo de INT_MIN e INT_MAX, conforme definido no cabeçalho <climits> .

A conclusão: depende de qual arquitetura você está trabalhando. Qualquer outra suposição é falsa.

Jérôme Radix
fonte
12

Não, não há padrão para tamanhos de tipo. O padrão exige apenas que:

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

A melhor coisa que você pode fazer se desejar variáveis ​​de tamanhos fixos é usar macros como esta:

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

Então você pode usar WORD para definir suas variáveis. Não é que eu goste disso, mas é a maneira mais portátil .

Emiliano
fonte
4
O problema é que o WORD se espalha pelo programa em áreas que não são verdadeiramente dependentes de um tamanho fixo (veja alguns códigos do Windows). Como descobri, ao passar de um sistema de 16 bits para 32 bits, você acaba com o mesmo problema que o WORD deveria solucionar.
22411 lilburne
@ liburne É claro que você deve usar o WORD somente quando precisar de uma variável de tamanho fixo, como quando estiver lendo / gravando de / para um arquivo. Se um pedaço de código não é realmente dependente de um tamanho fixo, você deve usar variáveis ​​"int" normais.
Emiliano
3
A melhor coisa que você pode fazer para obter tamanhos portáteis deve ser#include <boost/cstdint.hpp>
kizzx2
11

Temos permissão para definir um sinônimo para o tipo para que possamos criar nosso próprio "padrão".

Em uma máquina na qual sizeof (int) == 4, podemos definir:

typedef int int32;

int32 i;
int32 j;
...

Portanto, quando transferimos o código para uma máquina diferente, na qual o tamanho de int longo é 4, podemos redefinir a ocorrência única de int.

typedef long int int32;

int32 i;
int32 j;
...
milan-j
fonte
1
Isso não é necessário, dado o cabeçalho padrão <stdint.h>(C99 e posterior, e o padrão C ++ adotado na versão C99 da biblioteca C).
21416 Keith Thompson
8

Para números de ponto flutuante, existe um padrão (IEEE754) : flutuadores são 32 bits e duplos são 64. Esse é um padrão de hardware, não um padrão C ++, portanto, os compiladores poderiam teoricamente definir float e dobrar para outro tamanho, mas na prática eu ' nunca vi uma arquitetura que usasse algo diferente.

Crashworks
fonte
2
No entanto, a conformidade com a IEEE 754 (também conhecida como IEC 559) é opcional no C ++ (provavelmente C também, mas não tenho certeza). Consulte std :: numeric_limits :: is_iec559.
Drew Hall
1
Então você não viu o compilador da TI para os DSP TMS320C28xx, onde doubletem o mesmo tamanho float(e into mesmo que char, ambos são 16 bits). Mas eles têm 64 bits long double.
starblue
7

Existe um padrão e ele é especificado nos vários documentos de padrões (ISO, ANSI e outros enfeites).

A Wikipedia possui uma ótima página que explica os vários tipos e o máximo que eles podem armazenar: Inteiro em Ciência da Computação.

No entanto, mesmo com um compilador C ++ padrão, você pode descobrir com relativa facilidade usando o seguinte snippet 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;
}

A documentação para std :: numeric_limits pode ser encontrada em Roguewave . Inclui uma infinidade de outros comandos que você pode chamar para descobrir os vários limites. Isso pode ser usado com qualquer tipo arbitrário que transmita tamanho, por exemplo std :: streamsize.

A resposta de João contém a melhor descrição, pois essas são garantidas. Não importa em que plataforma você está, há outra página boa que entra em mais detalhes sobre quantos bits cada tipo DEVE conter: tipos int , que são definidos no padrão.

Eu espero que isso ajude!

X-Istence
fonte
7

Você pode usar:

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

datatype = int, long intetc. Você poderá ver o tamanho do tipo de dados digitado.

População Xplosive
fonte
7

Quando se trata de tipos integrados para diferentes arquiteturas e diferentes compiladores, basta executar o código a seguir na sua arquitetura com o seu compilador para ver o que ele gera. Abaixo mostra o meu Ubuntu 13.04 saída do (Raring Ringtail) de 64 bits g ++ 4.7.3. Observe também o que foi respondido abaixo e é por isso que a saída é ordenada como tal:

"Existem cinco tipos de números inteiros assinados padrão: char assinado, int curto, int, longo int e longo longo int. Nesta lista, cada tipo fornece pelo menos tanto armazenamento quanto os que o precedem na 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
fonte
sizeof(char)não deve ser incluído.
Ven
3

Como mencionado, o tamanho deve refletir a arquitetura atual. Você pode dar uma olhada limits.hse quiser ver como o seu compilador atual está lidando com as coisas.

John T
fonte
Obrigado, mas gostaria de saber os tamanhos para as arquiteturas que não tenho (como 64 bits). Isso só conversa tutorial sobre 32bits monumentos arquitectónicos e ...
Jérôme
2

Como outros já responderam, todos os "padrões" deixam a maioria dos detalhes como "implementação definida" e afirmam apenas que o tipo "char" possui uma largura mínima de "char_bis" e que "char <= short <= int <= long < = long long "(float e double são praticamente consistentes com os padrões de ponto flutuante IEEE, e long double é tipicamente igual a double - mas pode ser maior nas implementações mais atuais).

Parte das razões para não ter valores muito específicos e exatos é que linguagens como C / C ++ foram projetadas para serem portáveis ​​para um grande número de plataformas de hardware - incluindo sistemas de computador nos quais o tamanho da palavra "char" pode ser de 4 bits ou 7 bits, ou até mesmo algum valor diferente dos computadores "8 / 16- / 32- / 64-bits" aos quais o usuário comum de computador doméstico está exposto. (O tamanho da palavra aqui significa quantos bits de largura o sistema normalmente opera - Novamente, nem sempre são 8 bits como os usuários de computadores domésticos podem esperar.)

Se você realmente precisa de um objeto (no sentido de uma série de bits representando um valor integral) de um número específico de bits, a maioria dos compiladores possui algum método para especificar isso; Mas geralmente não é portátil, mesmo entre compiladores feitos pela empresa ame, mas para plataformas diferentes. Alguns padrões e práticas (especialmente limits.he semelhantes) são comuns o suficiente para que a maioria dos compiladores tenha suporte para determinar o tipo mais adequado para um intervalo específico de valores, mas não o número de bits usados. (Ou seja, se você sabe que precisa manter valores entre 0 e 127, pode determinar que seu compilador suporta um tipo "int8" de 8 bits, que será grande o suficiente para manter toda a faixa desejada, mas não algo como um tipo "int7", que seria uma correspondência exata para 7 bits.)

Nota: Muitos pacotes de código-fonte Un * x usavam o script "./configure" que analisará os recursos do compilador / sistema e produzirá um Makefile e config.h adequados. Você pode examinar alguns desses scripts para ver como eles funcionam e como eles examinam os recursos do sistema / compilador e seguem sua liderança.

CM
fonte
1

Se você estiver interessado em uma solução C ++ pura, usei modelos e apenas o código padrão C ++ para definir tipos em tempo de compilação, com base no tamanho dos bits. Isso torna a solução portátil entre os compiladores.

A idéia por trás é muito simples: crie uma lista contendo os tipos char, int, short, long, long long (versões assinadas e não assinadas) e verifique a lista e, usando o modelo numeric_limits, selecione o tipo com o tamanho especificado.

Incluindo esse cabeçalho, você tem 8 tipos stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

Se algum tipo não puder ser representado, ele será avaliado como stdtype :: null_type também declarado nesse cabeçalho.

O CÓDIGO ABAIXO É DADO SEM GARANTIA, VERIFIQUE DUPLO.
Eu também sou novo na METAPROGRAMMING, sinta-se livre para editar e corrigir este código.
Testado com DevC ++ (portanto, uma versão do gcc em torno 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;

}
user781847
fonte
0
unsigned char bits = sizeof(X) << 3;

onde Xestá um char, int, longetc .. lhe dará o tamanho de Xem bits.

user3154672
fonte
1
um caractere nem sempre é de 8 bits; portanto, sua expressão não funcionará em arquiteturas com caracteres que não sejam de 8 bits . Apenas sizeof(type)*CHAR_BITretém
phuclv 5/02/2015
Mesmo se CHAR_BITfosse garantido ter 8 bits, << 3é apenas uma maneira ofuscada de escrever * 8ou * CHAR_BIT.
Keith Thompson
0

De Alex B O padrão C ++ não especifica o tamanho dos tipos integrais em bytes, mas especifica os intervalos mínimos que eles devem poder manter. Você pode inferir o tamanho mínimo em bits do intervalo necessário. Você pode deduzir o tamanho mínimo em bytes disso e o valor da macro CHAR_BIT que define o número de bits em um byte (em todas as plataformas, exceto as mais obscuras, é 8 e não pode ser inferior a 8).

Uma restrição adicional para char é que seu tamanho é sempre 1 byte ou bits CHAR_BIT (daí o nome).

Os intervalos mínimos exigidos pelo padrão (página 22) são:

e tipos de dados no MSDN:

caractere assinado: -127 a 127 (observe, não -128 a 127; isso acomoda plataformas de complemento de 1) caractere não assinado: 0 a 255 caractere "comum": -127 a 127 ou 0 a 255 (depende do sinal de char padrão) assinado curto: -32767 a 32767 sem sinal abreviado: 0 a 65535 assinado int: -32767 a 32767 int sem sinal assinado: 0 a 65535 assinado longo: -2147483647 a 2147483647 sem sinal longo: 0 a 4294967295 longo assinado: -9223372036854775807 a 922337203685 longo long: 0 a 18446744073709551615 Uma implementação C ++ (ou C) pode definir o tamanho de um tipo em bytes sizeof (type) para qualquer valor, desde que

a expressão sizeof (type) * CHAR_BIT avalia o número de bits suficiente para conter os intervalos necessários e a ordem do tipo ainda é válida (por exemplo, sizeof (int) <= sizeof (long)). Os intervalos específicos da implementação reais podem ser encontrados no cabeçalho em C ou em C ++ (ou melhor ainda, std :: numeric_limits no cabeçalho).

Por exemplo, é assim que você encontrará o alcance 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();

Isso está correto, no entanto, você também estava certo ao dizer que: char: 1 byte curto: 2 bytes int: 4 bytes de comprimento: 4 bytes flutuante: 4 bytes duplo: 8 bytes

Como as arquiteturas de 32 bits ainda são as padrão e as mais usadas, elas mantêm esses tamanhos padrão desde os dias anteriores a 32 bits, quando a memória estava menos disponível, e para compatibilidade e padronização anteriores, ela permaneceu a mesma. Mesmo sistemas de 64 bits tendem a usá-los e têm extensões / modificações. Consulte isso para obter mais informações:

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

JCoder
fonte
0

Percebo que todas as outras respostas aqui se concentraram quase exclusivamente em tipos integrais, enquanto o questionador também perguntou sobre pontos flutuantes.

Não acho que o padrão C ++ exija, mas os compiladores para as plataformas mais comuns hoje em dia geralmente seguem o padrão IEEE754 para seus números de ponto flutuante. Esse padrão especifica quatro tipos de ponto flutuante binário (além de alguns formatos BCD, aos quais nunca vi suporte nos compiladores C ++):

  • Meia precisão (binária16) - significando de 11 bits, intervalo de expoentes -14 a 15
  • Precisão única (binária32) - significando de 24 bits, intervalo de expoentes -126 a 127
  • Dupla precisão (binária64) - significando de 53 bits, intervalo de expoentes-1022 a 1023
  • Precisão quádrupla (binária128) - significando de 113 bits, intervalo de expoentes -16382 a 16383

Como isso é mapeado para os tipos C ++? Geralmente os floatusos precisão única; assim sizeof(float) = 4,. Em seguida, doubleusa precisão dupla (acredito que essa é a fonte do nome double) elong double pode ser precisão dupla ou quádrupla (é quádrupla no meu sistema, mas em sistemas de 32 bits pode ser dupla). Não conheço nenhum compilador que ofereça pontos flutuantes de meia precisão.

Em resumo, este é o habitual:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 ou 16
celticminstrel
fonte
Engraçado que cheguei a essa pergunta como parte de me perguntar por que Jeff usa mais bytes do que ele precisa.
Aniruddha Varma
-2

Você pode usar variáveis ​​fornecidas por bibliotecas como OpenGL , Qt , etc.

Por exemplo, o Qt fornece qint8 (com garantia de 8 bits em todas as plataformas suportadas pelo Qt), qint16, qint32, qint64, quint8, quint16, quint16, quint32, quint64, etc.

Lawand
fonte
1
Não responde à pergunta #
2145 EvilTeach
-8

Em uma máquina de 64 bits:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8
user2826084
fonte
2
Em algumas máquinas de 64 bits, intsão 8 bytes, mas a outra não é garantida. Não há nada que diga que chardeve ter apenas 8 bits. É permitido ter sizeof(void*)==464 bits.
SkyKing
-10

Existem quatro tipos de números inteiros com base no tamanho:

  • número inteiro curto: 2 bytes
  • número inteiro longo: 4 bytes
  • longo inteiro longo: 8 bytes
  • número inteiro: depende do compilador (16 bits, 32 bits ou 64 bits)
ricky
fonte
11
Falso, todos eles dependem da arquitetura, com os intervalos mínimos descritos em uma das outras respostas. Nada impede uma implementação ter short, inte longtodos os inteiros de 32 bits.
Matteo Italia
Você nem usou os nomes corretos para os tipos. Os nomes usam a palavra-chave int, não a palavra "número inteiro".
Keith Thompson