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.

Por dentro do Sega Game Gear

Sega Game Gear

E para concluir os posts (e vídeos) sobre videogames da Tectoy, vamos dar uma olhada no Game Gear. Já falei dele lá em 2009, mais especificamente sobre os problemas com os capacitores eletrolíticos. Este post seria então apenas um complemento do que já falei lá.

Primeiro segue o vídeo:


No vídeo eu não mostrei o Game Gear onde foi feita a troca dos capacitores. É o mesmo do post de 2009, mas segue a foto com maior resolução:

Sega Game Gear PCB

O VDP é o CI 315-5377 e ele vai ligado a uma memória RAM externa de 32k x 8 bits. Já o processador Z80 está dentro do CI 315-5378A que inclui também o controlador de I/Os e o do LCD. Ele usa uma memória externa de 8k x 8 bits. A placa do áudio, com saída para alto falante ou fone de ouvido é esta aqui, com um CI TBA2822:

Sega Game Gear audio PCB

E a placa da fonte, de onde saem o +5V para a parte lógica e o 34V para o LCD, com um CI MB3775:
Sega Game Gear placa da fonte

Agora as placas dos dos cartuchos. A primeira foto é do cartucho Sonic original da Sega. A segunda foto é do cartucho "genérico" Rei Leão (Lion King):

Sega Game Gear Cartridge PCB

Cartucho de Game Gear Genérico

Por dentro de um osciloscópio Engro ORC-10 ou "Quer ganhar um osciloscópio velho? Leia aqui!

Osciloscópio Engro ORC-10
Este osciloscópio (Engro ORC-10) já foi assunto de um post lá em 2012 e faltava um vídeo pra ele. A foto acima, do post antigo, é de como ele estava em 2012. Ele ficou na casa da minha mãe e só o trouxe pra casa quando me mudei. No apartamento onde morava não tinha lugar pra ele...

Pois então, depois desses anos lá na casa da minha mãe, ele agora está assim:

Osciloscópio Engro ORC-10
Os plugs bananas foram para na fonte de bancada que meu sobrinho montou enquanto fazia o curso técnico. Os dois knobs brancos que faltam eu nem sei o que aconteceu. Por dentro ele não foi tocado, até a gravação do vídeo abaixo:


E é isso mesmo pessoal, eu tenho muita coisa acumulada aqui que era pra um dia consertar ou fazer algo de útil, mas que não tenho tempo pra mexer. Está na hora de esvaziar um pouco o quarto de bagunça laboratório. O osciloscópio será de quem me mandar um e-mail pedindo para marcar um dia para vir pegar aqui em casa e sem me perguntar onde eu moro... ;-)

Conversor de arquivos binários para headers em C (arquivos .h)

Conversor Binario para header (.h)

Algumas vezes quando preciso fazer algo mais rápido ou automatizado escrevo umas linhas de código e gero um programinha para resolver o problema. Nada muito elaborado e só para problemas pontuais. Geralmente o código é usado só uma vez e fica esquecido em alguma pasta. E acaba que preciso novamente do mesmo código anos depois e não lembro onde deixei ou, pela ação de Murphy, apaguei o programinha numa limpeza ou formatação.

Para evitar que isso aconteça vou ver se salvo estas pequenas ferramentas no Github. Assim terei uma cópia de segurança fora dos meu PC e backups, além de (quem sabe) poder ser útil para alguém. Um outro beneficio é que terei que ter mais cuidado com o código e comentários, afinal estará a vista de outras pessoas.

Para começar coloquei o programa "bintoh" que foi feito para um projetinho que estou desenvolvendo. Minha necessidade era a de converter um arquivo binário que antes era gravado em uma EPROM (.bin) em um arquivo header em C (.h), para ser incluído no código de um projeto com microcontrolador (ARM Cortex M3). Funciona por linha de comando (veja imagem acima, rodando no PowerShell), bastando informar o nome da tabela, arquivo de entrada e arquivo de saída. Ele gera também um define com o tamanho da tabela.

Antigamente eu criava a maioria destas ferramentas de software em VB6 e depois passei a usar (e ainda uso) o VB.NET 10. Mas eu tento variar de vez em quando com Python, Javascript ou o bom e velho C puro. O bintoh era pra ter sido feito em VB.Net também, mas acabei fazendo em C já que não precisa de uma UI cheia de flu-flus...

Como é uma ferramenta para uso pessoal ele tem suas limitações (e falta delas). Ele não checa as extensões dos arquivos, que só precisa existir para ser convertido. Isso acabou transformando o programa em um conversor "universal" de arquivos para headers C. Para mim isso é uma vantagem até e devo usar em breve para outra coisa aqui.

Aproveitando a oportunidade deixa eu testar aqui o formatador de código hilite.me (Vou precisar formatar outros códigos pra postar aqui, num futuro post). O código abaixo é do bintoh e até que ficou bonito:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
    Bintoh - Binary to c header file converter
    Rodrigo Feliciano - 08/02/2017
*/
#include "stdio.h"

#define MAX_FILE_SIZE   524288  /* bytes */

int main(int argc, char *argv[]) {
    FILE *infile;   /* Binary file - input */
    FILE *outfile;  /* Header file - output */
    int chrin = 0;  /* Temp char input */
    int bytecount = 0;
    int i = 0;
    
    if(argc == 4)
    {
        infile = fopen(argv[2],"rb");   /* open input file for binary read */
    
        if(infile == 0)
        {
            printf("\n\nInput file error...\n\n");    /* No file... */
        }else
        {
            fseek(infile, 0L, SEEK_END);
            bytecount = ftell(infile);      /* Get the number of bytes in the file */
            rewind(infile);
            
            if(bytecount <= MAX_FILE_SIZE)
            {
                outfile = fopen(argv[3],"w");   /* Open the output file for write */
                
                if(outfile == 0)
                {
                    printf("Output file error...");
                }else
                {
                    fprintf(outfile,"/* Bintoh - Bin to Header file converter */\n");
                    fprintf(outfile,"\n#ifndef %s_H_",argv[1]);
                    fprintf(outfile,"\n#define %s_H_\n",argv[1]);
                    fprintf(outfile,"\n#define    FTABLE_SIZE    %i",bytecount);
                
                    fprintf(outfile,"\n\nconst unsigned char %s[%i] = \n{\n",argv[1],bytecount);
                
                    while((chrin = fgetc(infile)) != EOF)
                    {
                        if(i >= 7)  /* Number of items in a row - 1 */
                        {
                            fprintf(outfile,"0x%02x,\n",chrin); /* Last item in a row */
                            i=0;
                        }else if(i == 0)
                        {
                            fprintf(outfile,"    0x%02x,",chrin);   /* first item in a row */
                            i++;
                        }else
                        {
                            fprintf(outfile,"0x%02x,",chrin);   /* item in a row */
                            i++;
                        }
                    }
                
                    fprintf(outfile,"};\n\n\n#endif /* %s_H_ */",argv[1]);
                    fclose(outfile);
                }
            }else
            {
                printf("\nInput file too big!");
                printf("\nMaximum file size: %i bytes",MAX_FILE_SIZE);
                printf("\nInput file size: %i bytes\n\n",bytecount);
            }
            fclose(infile);
        }
    }else
    {
        printf("\nCreate a C Header file from a binary file\n");
        printf("\nusage: bintoh [table_name] [input_filename] [output_filename]\n\n");
    }
    
    return 0;
}

Por dentro do Master System da TecToy

Master System TecToy

Continuando os posts sobre videogames, desta vez trago pra vocês o Master System da TecToy. Na foto acima vemos o Master System e o Master System II. O II pode confundir um pouco, pois a TecToy chamou ele de 2, mas só muda a ROM interna.

Mas vamos lá, primeiro o vídeo e depois as fotos e comentários, como sempre:



A foto da placa do videogame (PCB):

PCB do Master System TecToy

O CI grandão no centro em cima, é um Z80 e os dois CIs de baixo são as memorias ligadas a seu barramento. A RAM é uma D4168C da NEC (8k x 8) e a ROM é a que fica entre o Z80 e a RAM:
CPU do Master System TecToy

O CI 315-5216 é o controlador de IOs. Os joysticks vão ligados diretamente nele:
315-5216 Master System TecToy

O encoder RGB é o manjado MC1377P:
MC1377 na placa do Master System TecToy

E o VDP 315-5124 com duas memórias iguais a RAM do Z80. Isso dá 16k x 8 para o vídeo:
VDP 315-5124 na placa do Master System TecToy

Por dentro de um Sega Power Base (conversor de Master System para Mega Drive)

Aproveitando o post (e o vídeo) anterior trago pra vocês uma vista interna do adaptador de cartuchos de Master System para Mega Drive da TecToy (conhecido lá fora como Sega Power  Base). Ele não tem nada demais, sendo só um conector para cartuchos de Master System na parte de cima e uma placa com as conexões para a entrada de cartucho do Mega Drive. Por fora ele é assim:


E segue o "por dentro" em vídeo:



A vista por baixo do aparelho:

Existe uma versão dele no formato de um cartucho, que não é tão estilosa mas é mais prática. E também existe a versão feita em casa. Existe um tópico clássico sobre como montar um (com o esquema) lá no AtariAge. Não funciona com todos os jogos, mas já quebra um galho. A diferença para estes jogos parece ser o problema de o Mega Drive não ter um ROM de inicialização, como o Master System. No adaptador original isso é contornado com uma CK2605 (PAL?  GAL?) ali no canto da placa:
O código para este CI e mais informações estão disponíveis lá no SMSPower.

Por dentro de um Mega Drive americano (Sega Genesis)

Sega Genesis - Mega Drive Americano

Esse aí de cima é meu Sega Genesis (Mega Drive americano) velho de guerra. Pra dar uma ideia de como faz tempo que ele está comigo basta dizer que comprei o videogame no Ibazar. Ele estava parado já há alguns anos e agora vai pra um novo dono. Mas antes disso vamos ao nosso tradicional "por dentro". Primeiro em vídeo:

[Vídeo retirado em 24/05/2017 - Estava fora de foco, tenho que regravar!]

O vídeo ficou ruim e meio sem foco e não tive tempo de regravar. Tenho que ver isso no celular antes de gravar novos vídeos. Mas, para compensar, seguem as fotos começando por uma vista geral da placa do console:
Sega Genesis - Mega Drive Americano - PCB

O processador é um Motorola MC68000 de 16 bits rodando a 7,6MHz. Ele vai ligado a duas memórias RAM de 32k x 8 bits. 
Sega Genesis - Mega Drive Americano - Processador

Agora o CI CXA1145, encoder RGB para vídeo composto. Ali no canto esquerdo dá pra ver os dois reguladores 7805 sem o dissipador de calor. Aquele DB9 ao lado do modulo de RF não tem furo no painel e não sei qual a sua função.
Sega Genesis - Mega Drive Americano - Modulador de RF

O VDP 315-5313 vai ligado a duas memorias de 64k x 4bits dual port :
Sega Genesis - Mega Drive Americano - VDP

O Z80 e sua RAM 6264 (8k x 8) responsável pelo som e pela retrocompatibilidade com jogos do Master System. Ali em cima no canto esquerdo vemos o CI do som Yamaha YM2612:
Sega Genesis - Mega Drive Americano - Z80

O Mega Drive 1 tem um CI amplificador de áudio (CXA-1034 2 x 30mW) só para a saída de fones. Nos fones o som é estéreo, mas na saída de RF ele é mono.
Sega Genesis - Mega Drive Americano - Amplificador de áudio

A placa do Joystick com um CI 74HC157 (Mux 2x1):

Joystick Mega Drive

Como editar arquivos 3GP no Sony Vegas

Pois é, consegui abrir os arquivos 3GP no Sony Vegas (ver post anterior). Encontrei uma solução num site em espanhol que não consigo encontrar de novo, então fico devendo o link e os créditos.

É bem simples, basta instalar o QuickTime e "magicamente" o Vegas consegue "enxergar" os arquivos 3GP. Dizem que funciona também se instalar o "QuickTime Alternative", mas não testei.