sábado, 25 de fevereiro de 2017

Quantos bytes uma variável float ocupa? E uma int?

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:

Compilador Dev C
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):

Compilador C

Compilador C
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:

Compilador C

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):
Console NIOS II
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):
CodeWarrior HCS08

No primeiro teste selecionei um microcontrolador MC9S08QE128 de 8 bits:
CodeWarrior HCS08

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.

CodeWarrior Coldfire Wizard
E o resultado:
CodeWarrior Coldfire
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:

Turbo C

O Turbo C é do tempo do DOS e o resultado não poderia ser outro:
Turbo C
É 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.

Um comentário:

1. Alguns comentários são moderados automaticamente. Caso isso ocorra pode levar algum tempo até que eu veja e o libere.
2. Comentários fora do assunto do post podem ser apagados.
3. Não, eu não posso consertar os seus aparelhos!

Related Posts Plugin for WordPress, Blogger...