Bom, dias atrás um colega virou pra mim e perguntou:
- Quantos bytes tem uma variável float?
Respondi de bate-pronto:
- Depende... Mas na maioria dos casos são quatro.
E mostrei pra ele um velho truque para saber quantos bytes um tipo de variável ocupa (em C):
printf("%i",sizeof(float)); /* troque o float para o tipo desejado */
Então, em 99% dos casos você vai ver que o float ocupa quatro bytes (32 bits). O grande problema em C é o tal do int, que depende do processador e/ou do compilador. Normalmente o pessoal que programa para PC não se preocupa muito com isso, mas para sistemas com microcontroladores pode dar uma dor de cabeça quando for salvar a variável (numa EEPROM por exemplo). A melhor opção é não usar int. Não custa nada incluir a inttypes.h e usar os tipos dela (int8_t, uint8_t e por aí vai) ou criar os seus próprios typedefs num canto qualquer.
Pois então, depois da pergunta fiquei curioso e resolvi testar alguns compiladores e sistemas diferentes. O programa de testes é este:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| #include <stdio.h>
int main(int argc, char** argv)
{
printf("\nInt = %i bytes",sizeof(int));
printf("\nFloat = %i bytes",sizeof(float));
printf("\nFloat* = %i bytes",sizeof(float*));
printf("\nInt* = %i bytes",sizeof(int*));
printf("\n\n\n");
return 0;
}
|
As linhas 6 e 7 são pra mostrar a quantidade de bytes dos int e float. Incluí logo depois (linhas 9 e 10) um teste para os ponteiros para estes mesmos tipos. Claro que os ponteiros ocuparão a mesma quantidade de bytes, mas vai que alguém resolveu inventar moda. Nunca se sabe...
Para começar, o bom e velho Dev C que mantenho instalado e uso quando preciso gerar um
programinha rápido. E o resultado foi este:
Ele usa o GCC 4.8.1 para 64 bits e o resultado foi 4 bytes para int e float e 8 bytes para os ponteiros. Testado no Windows 7 de 64 bits. Aí vemos que o int não segue o número de bits do sistema, parece que ele vai ficar nos 32 bits mesmo.
Agora os testes com compiladores online, via browser (como é bom viver no futuro):
No primeiro caso o
jdoodle deu nó (warnings) com o %i no printf, mas funcionou direitinho (o sizeof retorna um int). E junto com o
Codingground deu o mesmo resultado do Dev C.
Dos compiladores online o que deu uma pequena diferença foi o
Codechef com ponteiros de 32 bits:
Um sistema diferente que testei foi o Nios II da Altera, numa plaquinha chinesa com uma FPGA Cyclone IV (já tinha tudo ligado e instalado no PC):
O NIOS II pode ser definido como um "microcontrolador por software" e o teste confirma a sua natureza de 32 bits.
E nos microcontroladores? Como não queria perder tempo ligando uma placa e instalando uma IDE resolvi testar no CodeWarrior 6.3 que tenho instalado numa máquina virtual com windows XP. Nele eu posso simular o software sem precisar gravar numa placa.
Usei o Wizard dele e gerei um programa mínimo com o Processor Expert:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| /* Code Warrior */
int var_int,var_float,pointer_float,pointer_int,res;
void main(void)
{
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
/* Write your code here */
/* For example: for(;;) { } */
for(;;)
{
var_int = sizeof(int);
var_float = sizeof(float);
pointer_float = sizeof(float*);
pointer_int = sizeof(int*);
res = var_int + var_float + pointer_float + pointer_int;
}
}
|
Salvei os resultados dos sizeof em variáveis para aparecer no simulador e a soma ali na linha 21 é só pra ele gerar o código. Sem ela o CodeWarrior dá um de esperto e não compila as linhas anteriores, já que não serviriam pra nada.
Algo interessante é que numa das telas do wizard dá pra escolher o tamanho do double, mas não o tamanho do float (ou não tem ou é IEEE32):
No primeiro teste selecionei um microcontrolador MC9S08QE128 de 8 bits:
E tá lá o float de 32 bits (4 bytes). O interessante (e esperado) são os ponteiros para 16 bits. Já o int são dois bytes.
Agora passando para Coldfire V1 (MCF51QE128 de 32 bits) a tela do wizard muda e temos a opção do float e double de 64 bits.
E o resultado:
Eita, temos um problema aí. Eu selecionei o float de 64 bits, mas ele saiu com 32 bits. Provavelmente um erro na tela do wizard. Os ponteiros são de 32 bits, de acordo com a arquitetura dos Coldfires. Era pra testar com o CodeWarrior para Coldfire V2, mas ele está instalado num HD antigo e não quis abrir meu PC pra fazer o teste.
Acho que já ficou claro então que o float é de 32 bits e o int varia. Mas fiz um último teste, com o saudoso Turbo C. Como vivemos no futuro posso rodar o compilador ancião
diretamente no browser:
O Turbo C é do tempo do DOS e o resultado não poderia ser outro:
É igual ao do microcontrolador de 8 bits da Freescale: int de 2 bytes, float de 4 e endereços de 16 bits. Era assim nos tempos anteriores ao Pentium.