<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Márcio Scotuzzi Júnior</title>
    <description>The latest articles on Forem by Márcio Scotuzzi Júnior (@scotuzzijr).</description>
    <link>https://forem.com/scotuzzijr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F826395%2F37084737-7e5b-4ceb-b915-7df2f0b80dd3.jpg</url>
      <title>Forem: Márcio Scotuzzi Júnior</title>
      <link>https://forem.com/scotuzzijr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/scotuzzijr"/>
    <language>en</language>
    <item>
      <title>Virtualização, processos e fork bomb</title>
      <dc:creator>Márcio Scotuzzi Júnior</dc:creator>
      <pubDate>Tue, 10 Jun 2025 14:41:59 +0000</pubDate>
      <link>https://forem.com/scotuzzijr/virtualizacao-processos-e-fork-bomb-1hd0</link>
      <guid>https://forem.com/scotuzzijr/virtualizacao-processos-e-fork-bomb-1hd0</guid>
      <description>&lt;p&gt;Em maio de 2025, a OpenAI anunciou seu novo agente &lt;a href="https://openai.com/index/introducing-codex/" rel="noopener noreferrer"&gt;Codex&lt;/a&gt;, cujo diferencial é a execução paralela de tarefas, todas rodando diretamente na nuvem.&lt;/p&gt;

&lt;p&gt;Lendo sobre o Codex, comecei a refletir sobre virtualização, processos, contêineres e sobre como, muitas vezes, não paramos para observar mais de perto como certos recursos que usamos no dia a dia funcionam.&lt;/p&gt;

&lt;p&gt;A proposta deste texto, então, é "escovar bits" sobre alguns conceitos de sistemas operacionais, partindo da seguinte pergunta: rodar um fork bomb em uma máquina virtual pode comprometer os recursos da máquina hospedeira? E no caso de estarmos usando um contêiner Docker?&lt;/p&gt;

&lt;h2&gt;
  
  
  Vamos dar um passo atrás
&lt;/h2&gt;

&lt;p&gt;Para alguns, a resposta à pergunta acima pode parecer óbvia. Para outros, nem tanto. Há ainda um terceiro grupo que talvez se pergunte: o que é um fork bomb?&lt;/p&gt;

&lt;p&gt;Fork bomb é uma forma de gerar processos recursivamente. E, para garantirmos que estamos todos na mesma página, vamos recorrer ao &lt;a href="https://pt.wikipedia.org/wiki/Andrew_Stuart_Tanenbaum" rel="noopener noreferrer"&gt;Tanenbaum&lt;/a&gt; e sua definição de processo no livro &lt;a href="https://www.amazon.com.br/Sistemas-Operacionais-Modernos-Andrew-Tanenbaum/dp/8582606168" rel="noopener noreferrer"&gt;Sistemas Operacionais Modernos&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;O conceito mais central em qualquer sistema operacional é o processo: uma abstração de um programa em execução [...] A ideia principal é que um processo é uma atividade. Ele possui programa, entrada, saída e um estado.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assim, ao criarmos processos de forma recursiva e indefinida, passamos a consumir os recursos do sistema operacional, o que leva eventualmente ao esgotamento desses recursos e, consequentemente, à "quebra" do sistema.&lt;/p&gt;

&lt;p&gt;Para entendermos melhor como esse esgotamento acontece, precisamos detalhar como processos são criados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criação de processos
&lt;/h2&gt;

&lt;p&gt;Tanenbaum descreve quatro formas pelas quais um processo pode ser criado:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Durante a inicialização do sistema;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Através da execução de uma chamada de sistema de criação de processo por um processo em execução (este é o ponto central para entender o fork bomb);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A partir de uma solicitação do usuário para criar um novo processo;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pelo início de uma tarefa em lote (batch job).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Quando um sistema operacional é iniciado, diversos processos são carregados — alguns em primeiro plano, outros em segundo. Isso é necessário para o funcionamento adequado do sistema. A partir daí, todos os novos processos passam a ser criados a partir de processos já existentes. Cada processo possui informações importantes associadas, como endereçamento de memória.&lt;/p&gt;

&lt;p&gt;O ponto crucial aqui é que, embora um processo filho compartilhe algumas informações com o processo pai (aquele que o criou), cada processo tem seu próprio espaço de memória para escrita, o que garante que não haverá interferência mútua na execução de suas tarefas. Portanto, a criação de novos processos consome cada vez mais memória da máquina.&lt;/p&gt;

&lt;p&gt;E onde entra o fork? Em sistemas baseados em Unix, a chamada de sistema responsável pela criação de novos processos é justamente o fork().&lt;/p&gt;

&lt;p&gt;Agora que entendemos como os processos são criados e como o fork bomb pode causar o esgotamento de recursos, vamos analisar se isso também se aplica ao executar o fork bomb em uma máquina virtualizada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Máquinas virtuais
&lt;/h2&gt;

&lt;p&gt;Uma máquina virtual (VM) é um ambiente isolado que simula um computador físico completo, permitindo a execução de múltiplos sistemas operacionais independentes em um único hardware.&lt;/p&gt;

&lt;p&gt;O componente central da virtualização é o hipervisor (ou Virtual Machine Monitor – VMM), que é responsável por criar e gerenciar as VMs. Ele pode atuar diretamente sobre o hardware, sem necessidade de um sistema operacional intermediário, ou funcionar como uma aplicação instalada sobre um sistema operacional convencional. Neste segundo caso, o hipervisor depende do sistema operacional hospedeiro para acessar os recursos de hardware.&lt;/p&gt;

&lt;p&gt;Essa segunda abordagem é adotada por softwares como o &lt;a href="https://www.virtualbox.org/" rel="noopener noreferrer"&gt;VirtualBox&lt;/a&gt;. Nesses casos, como o sistema hospedeiro intermedia o acesso aos recursos, podemos limitar seu uso por parte da VM. Logo, ao executarmos um fork bomb em uma máquina virtual, o consumo de recursos ficará restrito àqueles previamente configurados — o que impede o esgotamento dos recursos da máquina física.&lt;/p&gt;

&lt;p&gt;E no caso do Docker?&lt;/p&gt;

&lt;h2&gt;
  
  
  Contêineres
&lt;/h2&gt;

&lt;p&gt;O Docker não utiliza hipervisor — e esse é justamente o seu diferencial. Enquanto as VMs simulam um computador completo em um ambiente isolado, os contêineres Docker isolam apenas os processos, utilizando o mesmo kernel da máquina hospedeira e seus recursos (abordagem bare metal).&lt;/p&gt;

&lt;p&gt;Portanto, um fork bomb executado dentro de um contêiner Docker pode sim consumir os recursos da máquina hospedeira e causar seu esgotamento.&lt;/p&gt;

&lt;h2&gt;
  
  
  É o fim?
&lt;/h2&gt;

&lt;p&gt;A explicação acima simplifica a questão ao propor a seguinte dicotomia: fork bomb em VM não é perigoso, mas em contêiner sim.&lt;/p&gt;

&lt;p&gt;A realidade, porém, é que em ambos os cenários podemos permitir ou impedir os efeitos de um fork bomb — pois tanto VMs quanto contêineres permitem configurar limites de uso de recursos.&lt;/p&gt;

&lt;p&gt;No fundo, o objetivo principal aqui era entender melhor os conceitos por trás da virtualização e dos processos.&lt;/p&gt;

&lt;p&gt;Para aprender como criar e se proteger de fork bombs, recomendo este &lt;a href="https://crg.eti.br/pt-br/post/forkbomb-do-codigo-a-defesa/" rel="noopener noreferrer"&gt;texto&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Embora tenha havido consulta a livros e outros materiais sobre o tema, erros conceituais podem eventualmente aparecer. Fique à vontade para deixar um comentário caso identifique algum equívoco :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>docker</category>
      <category>virtualmachine</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Aprenda padrões de projeto, mas não se apegue às implementações</title>
      <dc:creator>Márcio Scotuzzi Júnior</dc:creator>
      <pubDate>Fri, 23 May 2025 14:50:58 +0000</pubDate>
      <link>https://forem.com/scotuzzijr/aprenda-padroes-de-projeto-mas-nao-se-apegue-as-implementacoes-20o8</link>
      <guid>https://forem.com/scotuzzijr/aprenda-padroes-de-projeto-mas-nao-se-apegue-as-implementacoes-20o8</guid>
      <description>&lt;p&gt;A máxima "você não é o primeiro a passar por isso" se aplica muito bem à programação e, por isso, um bom ponto de partida para resolver um problema é ver como outras pessoas o solucionaram antes de você.&lt;/p&gt;

&lt;p&gt;Antes das IAs generativas, o lugar para onde todo dev corria ao pedir ajuda na internet era o Stack Overflow. Em todo o tempo que uso esse site, publiquei pouquíssimas perguntas lá — não por ter lidado com poucos bugs, mas porque a grande maioria das dores de cabeça que tive foram dores de cabeça que outras pessoas já tinham tido, e isso estava muito bem documentado, tanto no Stack Overflow quanto em outros fóruns.&lt;/p&gt;

&lt;p&gt;Na engenharia de software, a necessidade de documentar problemas recorrentes e as boas formas de resolvê-los deu origem aos padrões de projeto.&lt;/p&gt;

&lt;p&gt;Citando o site &lt;strong&gt;&lt;a href="https://refactoring.guru/design-patterns" rel="noopener noreferrer"&gt;Refactoring Guru&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Design patterns are &lt;strong&gt;typical solutions to common problems&lt;/strong&gt; in software design.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aqui é importante destacar que tais soluções são abordagens comuns para resolver esses problemas, mas não devemos nos apegar à implementação exata. O ideal é avaliar como podemos usar esses padrões para resolver os problemas específicos dos sistemas que desenvolvemos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Um exemplo real
&lt;/h3&gt;

&lt;p&gt;Atuando como desenvolvedor em uma empresa de crédito, precisei implementar uma funcionalidade de simulação de crédito rural. Sem entrar em detalhes das regras de negócio, o cenário era o seguinte:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O frontend enviava três informações: o tipo de simulação (mensal, trimestral, semestral), o valor simulado e uma taxa opcional (caso não fosse fornecida, cada tipo de simulação tinha uma taxa padrão definida);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Meu backend realizava o cálculo e retornava as informações necessárias, como o ID da simulação, valor da parcela etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meu primeiro pensamento foi usar uma factory, um padrão creacional em que subclasses herdam de uma classe pai que define uma estrutura geral (como métodos), sem se preocupar com a implementação específica de cada uma.&lt;/p&gt;

&lt;p&gt;No caso das simulações, a classe pai poderia definir um método para o cálculo das parcelas, e cada uma das três subclasses implementaria esse método de acordo com suas especificações.&lt;/p&gt;

&lt;p&gt;Como um bom júnior, caí de cabeça no código e, em pouco tempo, percebi que estava usando &lt;em&gt;Ctrl+C&lt;/em&gt; e &lt;em&gt;Ctrl+V&lt;/em&gt; demais.&lt;/p&gt;

&lt;p&gt;O problema era que a lógica para calcular o valor das parcelas era a mesma; eu só mudava os parâmetros de taxa e prazo com base no tipo de simulação. Ou seja, não precisava de três subclasses implementando o mesmo método da mesma forma. O que eu realmente precisava era instanciar uma única classe com parâmetros diferentes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnc6619ln2bsoasi01pg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnc6619ln2bsoasi01pg.png" alt="Image description" width="800" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essa foi a solução a que cheguei. Talvez exista uma forma melhor de resolver esse problema — mas o fato é que meus testes passaram, a comunicação com o frontend funcionou, e eu precisava entregar a task. Então subi assim mesmo.&lt;/p&gt;

&lt;p&gt;Em resumo, a mensagem que fica é: devemos sim estudar os padrões de projeto, mas é sempre importante parar um minuto para aplicá-los da forma que melhor se encaixe no nosso código — caso contrário, eles mais atrapalham do que ajudam.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>designpatterns</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Recriando o comando cat do Linux em C</title>
      <dc:creator>Márcio Scotuzzi Júnior</dc:creator>
      <pubDate>Tue, 27 Feb 2024 12:25:21 +0000</pubDate>
      <link>https://forem.com/scotuzzijr/recriando-o-comando-cat-do-linux-em-c-2mg5</link>
      <guid>https://forem.com/scotuzzijr/recriando-o-comando-cat-do-linux-em-c-2mg5</guid>
      <description>&lt;p&gt;No dia a dia, nós usuários de Linux costumamos utilizar uma série de programas simples, porém extremamente úteis. Um que eu utilizo com frequência é o &lt;strong&gt;cat&lt;/strong&gt; - que nos permite exibir no terminal o conteúdo de um arquivo. Porém, você já parou para pensar em como esse programinha funciona?&lt;/p&gt;

&lt;p&gt;Suponhamos que eu queira conferir o conteúdo do arquivo &lt;em&gt;toc_toc.txt&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksajx58p1pd031rad5u8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksajx58p1pd031rad5u8.png" alt="Image description" width="497" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao chamar o comando &lt;strong&gt;cat&lt;/strong&gt; eu forneço como argumento o arquivo que eu quero exibir e, como resposta, no terminal é exibido o que o tal arquivo contem. Portanto, se quisermos recriar esse comando, o primeiro passo será receber um argumento por linha de comando.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspizggosk3i81hpnf88t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspizggosk3i81hpnf88t.png" alt="Image description" width="782" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na linha 5 nós estamos definindo dois parâmetros para a função main:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;argc&lt;/strong&gt;: conta quantos argumentos foram passados pela linha de comando na hora que o programa foi executado;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;argv&lt;/strong&gt;: é um vetor com todos os argumentos passados&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note que todo programa terá, no mínimo, um argumento - o nome do programa. Por isso checamos se o &lt;strong&gt;argc&lt;/strong&gt; é menor do que 2, pois caso seja isso é um sinal de que o nome do arquivo que o &lt;strong&gt;cat&lt;/strong&gt; deverá exibir o conteúdo não foi fornecido. Nesse caso, exibimos uma mensagem informando a maneira correta de utilizar o programa e encerramos a execução com um código de erro.&lt;/p&gt;

&lt;p&gt;Se o programa recebeu os devidos argumentos quando foi executado, o próximo passo é abrirmos o arquivo cujo o nome foi informado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjtbtnm5vyfir82zlod2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjtbtnm5vyfir82zlod2.png" alt="Image description" width="782" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fazemos isso declarando um ponteiro para um arquivo e abrindo ele em seguida.&lt;/p&gt;

&lt;p&gt;Na linha 15 nós checamos se tudo ocorreu de forma adequada na abertura do arquivo. Caso algum problema tenha ocorrido, exibimos uma mensagem de erro e encerramos a exceução do programa.&lt;/p&gt;

&lt;p&gt;Por fim, temos um loop que irá ler caracter por caracter do nosso arquivo até chegar ao final - exibindo esses caracteres no terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F826mx4ad11eviunymg9x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F826mx4ad11eviunymg9x.png" alt="Image description" width="605" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após finalizarmos a leitura e exibição do conteúdo do arquivo, nós fechamos o arquivo e encerramos o programa.&lt;/p&gt;

&lt;p&gt;Agora é só compilar e testar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgx0iit8okcgqtovs2paq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgx0iit8okcgqtovs2paq.png" alt="Image description" width="800" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Funciona!!! &lt;/p&gt;

&lt;p&gt;Uma coisa importante a dizer é que a implementação do &lt;strong&gt;cat&lt;/strong&gt; original é bem mais complexa (&lt;a href="https://github.com/coreutils/coreutils/blob/master/src/cat.c" rel="noopener noreferrer"&gt;código fonte aqui&lt;/a&gt;) e tem 800 linhas. Porém, a ideia dessa implementação que fizemos é apenas entender como certos programas que utilizamos no dia a dia funcionam na sua forma mais básica. Aliás, apesar da nossa implementação ser muito mais simples que a original, se compararmos as saídas do nosso programa e do &lt;strong&gt;cat&lt;/strong&gt; do Linux, vamos ver que ambos produzem a mesma saída.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzt3z5saciitupobpwgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzt3z5saciitupobpwgg.png" alt="Image description" width="800" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tentar recriar esses utilitários de sistema operacional é uma ótima forma de dar os primeiros passos no desenvolvimento baixo nível e aprofundar os conhecimentos em linguagens como C. Por falar em baixo nível, como seria implementar o &lt;strong&gt;cat&lt;/strong&gt; em Assembly? Eu vou fazer os meus testes e volto para te contar.&lt;/p&gt;

&lt;p&gt;Fique bem até lá :)&lt;/p&gt;

</description>
      <category>c</category>
      <category>linux</category>
      <category>programming</category>
    </item>
    <item>
      <title>Por que a soma de um int com um float resulta em um float?</title>
      <dc:creator>Márcio Scotuzzi Júnior</dc:creator>
      <pubDate>Sun, 18 Feb 2024 23:00:24 +0000</pubDate>
      <link>https://forem.com/scotuzzijr/por-que-a-soma-de-um-int-com-um-float-resulta-em-um-float-5996</link>
      <guid>https://forem.com/scotuzzijr/por-que-a-soma-de-um-int-com-um-float-resulta-em-um-float-5996</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Dentro da computação, &lt;strong&gt;compiladores&lt;/strong&gt; é um dos meus assuntos favoritos. Eles são programas responsáveis por traduzir um código escrito em certa &lt;strong&gt;linguagem fonte&lt;/strong&gt; para uma outra &lt;strong&gt;linguagem alvo&lt;/strong&gt;. Geralmente, a linguagem alvo é o conjunto de instruções que o processador da sua máquina é capaz de executar. Além disso, o compilador é o cara responsável por exibir mensagens de erro horrorosas toda vez que a gente faz alguma merda no nosso código (e não adianta mentir, eu sei que você já passou por isso).&lt;/p&gt;

&lt;p&gt;Compiladores são fascinantes por si só, mas uma coisa legal sobre estudar esses softwares é o fato de precisarmos resgatar ou aprender sobre conceitos de &lt;strong&gt;arquitetura de computadores&lt;/strong&gt;, &lt;strong&gt;sistemas operacionais&lt;/strong&gt;, &lt;strong&gt;estruturas de dados&lt;/strong&gt; etc. Não só isso, nós nos vemos obrigados e pensar sobre algumas coisas que no dia a dia costumam passar batido. Por exemplo: &lt;strong&gt;por que somar um inteiro com um número de ponto flutuante sempre resulta em um número de ponto flutuante?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Entendendo tipos de dados
&lt;/h2&gt;

&lt;p&gt;Você já deve ter estudado os &lt;strong&gt;tipos de dados&lt;/strong&gt; de alguma linguagem: int, float, char, boolean, entre outros. Porém, você já se perguntou &lt;strong&gt;o que exatamente são os tipos de dados?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Um tipo de dado nada mais é do que &lt;strong&gt;um conjunto de valores que uma variável pode assumir&lt;/strong&gt; e esse conjunto de valores, por sua vez, &lt;strong&gt;compartilham de operações comuns entre eles.&lt;/strong&gt; Logo, dizer que os valores 17 e 42 são do tipo inteiro, significa que eles pertencem ao mesmo conjunto de valores que uma variável inteira poderá assumir justamente por eles compartilharem as mesmas operações - por exemplo, a soma. &lt;/p&gt;

&lt;p&gt;Quando computamos a expressão &lt;code&gt;17 + 42&lt;/code&gt; estamos somando esses dois valores (e obtendo o resultado 59). Vale dizer que &lt;strong&gt;um mesmo operador **(nesse caso, +) **pode representar diferentes operações.&lt;/strong&gt; Ao computar &lt;code&gt;"olá, " + "mundo!"&lt;/code&gt; nós não estamos realizando uma soma, mas sim uma concatenação - &lt;strong&gt;embora o operador seja o mesmo, a operação é outra.&lt;/strong&gt; Como resultado teríamos "olá, mundo!". E se tentarmos usar o operador + com um inteiro e uma string? &lt;strong&gt;Obtemos um erro.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj57fdasbn80wutigdh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj57fdasbn80wutigdh0.png" alt="Image description" width="692" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No exemplo acima estamos trabalhando com a linguagem Python e você pode reproduzir esse exemplo no próprio IDLE do Python. Note que quando uma string é o primeiro argumento fornecido para o operador +, o erro diz que só é permitido concatenar uma string com outra string. Já quando o primeiro argumento é um inteiro, o erro diz que o tipo de dado dos operandos não são suportados pelo operador. Em ambos os casos, a nossa tentativa é falha, justamente porque, sendo de tipos diferentes, &lt;strong&gt;inteiros e strings não compartilham das mesmas operações.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agora você deve estar pensando, &lt;strong&gt;se inteiros e números de ponto flutuante são de tipos diferentes, por que conseguimos somá-los?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Entendendo type casting
&lt;/h2&gt;

&lt;p&gt;Se você já estudou os tipos de dados de alguma linguagem, então deve ter estudado também sobre &lt;em&gt;type casting&lt;/em&gt; (ou conversão momentânea de tipos). Basicamente, é quando nós &lt;strong&gt;convertemos o tipo de um dado por um instante&lt;/strong&gt;. Se você já estudou Python, deve ter se deparado com isso:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F259khorb5y97qycc0cci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F259khorb5y97qycc0cci.png" alt="Image description" width="760" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O que aconteceu aqui? Simples! Por padrão, a função input trata todos os dados como string (exatamente o que eu faço quando vou modelar uma tabela no banco de dados e fico com preguiça de definir o tipo certo para cada coluna). Como já vimos antes, o operador + quando aplicado sobre strings realiza a operação de concatenação, logo, &lt;code&gt;"17" + "42"&lt;/code&gt; só pode resultar em 1742. E como lidar com isso? Assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F511la1ty0kf907a45mm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F511la1ty0kf907a45mm7.png" alt="Image description" width="760" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nós usamos a função int para converter o tipo de dado de string para inteiro. Note que &lt;strong&gt;isso só foi possível porque a string continha uma representação numérica&lt;/strong&gt; - experimenta digitar uma letra para ver se o interpretador não grita com você. &lt;/p&gt;

&lt;p&gt;Outra coisa importante a se dizer: &lt;strong&gt;a conversão de tipos é momentânea&lt;/strong&gt; e, caso queira persisti-la, deve-se armazenar o dado em uma variável ao realizar a conversão. &lt;/p&gt;

&lt;p&gt;Portanto, quando somamos um número inteiro com um número de ponto flutuante, o que acontece é um &lt;em&gt;type casting&lt;/em&gt; do int para float. A imagem abaixo mostra um exemplo de como os tipos de dados seguem os mesmos e o casting só ocorre na hora da operação.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycplesy613m296dyzaw3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycplesy613m296dyzaw3.png" alt="Image description" width="199" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repara em como x se mantem sendo um int, mesmo que para computar o valor de z ele tenha sido convertido para um float.&lt;/p&gt;

&lt;p&gt;E sim, eu sei que você já chegou nessa conclusão do &lt;em&gt;type casting&lt;/em&gt; sozinho, mas o que talvez não tenha ficado evidente é: &lt;strong&gt;por que isso acontece?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sejamos precisos (tanto quanto se pode)
&lt;/h2&gt;

&lt;p&gt;Eu pretendo escrever um texto só para discutir representação de números de ponto flutuante, mas a densidade desse assunto é proporcional a sua beleza. Portanto, vamos definir algumas coisas mais triviais apenas para podermos responder a pergunta inicial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operações com números inteiros são realizadas em uma região diferente das com números reais.&lt;/strong&gt; Para a primeira, temos a &lt;strong&gt;ALU&lt;/strong&gt; e para a segunda temos a &lt;strong&gt;FPU&lt;/strong&gt;. Isso acontece porque &lt;strong&gt;nós não representamos números inteiros da mesma forma que representamos números de ponto flutuante.&lt;/strong&gt; Quando a conversão de tipos ocorre ao somamrmos um int e um float, a escolha de converter o int para um float e não o contrário, está relacionada justamente com manter a precisão dos valores - pois &lt;strong&gt;representar um inteiro como um número real é mais propenso a manter a precisão do que representar um número real como inteiro.&lt;/strong&gt; Loucura né?&lt;/p&gt;

&lt;p&gt;Em resumo, quando somamos &lt;code&gt;17 + 42.0&lt;/code&gt; a &lt;strong&gt;ALU&lt;/strong&gt; vai se encarregar de transformar essa representação inteira para uma representação de ponto flutuante e irá chamar a &lt;strong&gt;FPU&lt;/strong&gt; para realizar a operação. &lt;strong&gt;O resultado final acaba sendo um float porque quem computou o valor foi a FPU&lt;/strong&gt; - que só trabalha com números de ponto flutuante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Ufa! Parece que chegamos ao fim. Talvez a minha explicação não tenha sido a melhor ou a mais completa. Além disso, talvez eu tenha cometido algum erro conceitual no caminho. Para ambos os casos, sinta-se livre para deixar um comentário. &lt;/p&gt;

&lt;p&gt;No mais, estou indo embora. &lt;/p&gt;

&lt;p&gt;Fique bem e até :)&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
