No caso do C++, a especificação da linguagem define que byte é a unidade de armazenamento e terá tamanho suficiente (em bits consecutivos) para acomodar o conjunto de caracteres básicos do ambiente de execução e os 8 bits do UTF-8. Atendidos estes requisitos, cada implementação tem liberdade de definir o tamanho em bits de um byte. Ainda está previsto que o tamanho de um char, em bytes é 1 (ou seja, sizeof(char)==1). O Stroustrup, em "The C++ Programming Language" prefere descrever que o operador sizeof retorna a quantidade de chars ocupada por uma expressão ou tipo em vez de quantidade de bytes. Então, em se tratando de C++, não devemos assumir que um byte tenha 8 bits, embora este seja o caso mais comum.
O tamanho dos diversos tipos fundamentais
Não é incomum encontrarmos em materiais sobre a linguagem, até mesmo em alguns livros, tabelas especificando o tamanho em bits, ou em bytes, para os tipos de dados fundamentais da linguagem, como neste exemplo:
Em relação aos tipos inteiros, a linguagem apenas estabelece que cada um dos tipos signed char, short int, int, long int e long long int utilizam, no mínimo, o mesmo espaço de armazenamento do seu anterior nesta ordem. Ou seja, podemos resumir a regra a isto:
1 == sizeof(char) <= sizeof(short int) <= sizeof(int) <= sizeof(long int) <= sizeof(long long int)
Percebam que, embora isto seja incomum na prática, nada impede que um long long int, por exemplo, possua o mesmo tamanho, em bytes, de um short int e portanto, o mesmo intervalo de armazenamento.
Ao declararmos uma variável apenas como int, ela terá, normalmente o tamanho da palavra de máquina para aquela arquitetura e irá oferecer a aritmética mais eficiente disponível para inteiros.
Quanto aos tipos em ponto-flutuante a linguagem estabelece que existem três tipos: float, double e long double. Cada um destes, na ordem apresentada, oferece, no mínimo, a precisão do antecessor. Geralmente as implementações seguem o padrão IEEE 754-1985, e utilizam 32 bits para os números em precisão simples e 64 bits para a precisão dupla. Já a precisão extendida (long double), não é um tamanho padronizado, correspondendo, na arquitetura x86 ao formato extendido de 80 bits.
Verifique o tamanho de cada tipo em seu compilador com o código a seguir [disponível no Ideone]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <iostream> using namespace std; int main() { cout << "signed char: " << sizeof(signed char) << endl; cout << "short int: " << sizeof(short int) << endl; cout << "int: " << sizeof(int) << endl; cout << "long int: " << sizeof(long int) << endl; cout << "long long int: " << sizeof(long long int) << endl; cout << "float: " << sizeof(float) << endl; cout << "double: " << sizeof(double) << endl; cout << "long double: " << sizeof(long double) << endl; return 0; } |
Os tamanhos exatos em <cstdint>
Se precisarmos de tipos inteiros de tamanho determinado, podemos recorrer ao #include<cstdint>. Estão previstos tipos inteiros com ou sem sinal para os tamanhos de 8, 16, 32 e 64 bits, como segue:
// Com sinal
int8_t
int16_t
int32_t
int64_t
// Sem sinal
uint8_t
uint16_t
uint32_t
uint64_t
int8_t
int16_t
int32_t
int64_t
// Sem sinal
uint8_t
uint16_t
uint32_t
uint64_t
O padrão da linguagem, no entanto, define que estes tipos são opcionais naquele header. Ou seja, se a implementação em questão não puder oferecer algum destes tamanhos, ela pode omiti-lo, o que causaria erro de compilação nos programas que os usam.
O emprego sem critérios destes tipos podem reduzir, portanto, a portabilidade do código, o que se opõem ao objetivo de criação deste include. Devemos usa-los com precaução, apenas nos casos em que se quer a garantia de tamanho para uma determinada variável ou campo de struct ou class. Exemplos de aplicação seria onde a interface com outros dispositivos ou aplicações ocorrem em binário, como geração de arquivos binários que serão lidos por outros aplicativos ou na construção de devices drivers.
Nenhum comentário:
Postar um comentário