Linguagens de Programação

Linguagens de programação são a forma que usamos para dizer ao computador o que ele deve fazer, e para entendê-las de verdade precisamos conhecer sua história, seus objetivos e como funcionam na prática. Neste guia, começamos pela origem, passamos pelas ferramentas que transformam o código e terminamos com exemplos em algumas das linguagens mais usadas.

O que são linguagens de programação

Linguagens de programação são conjuntos de regras, palavras e símbolos que permitem escrever instruções para um computador. Em outras palavras, elas fazem a ponte entre o raciocínio humano e os sinais elétricos que o hardware entende.

Cada linguagem define uma sintaxe, ou seja, a forma correta de escrever, e uma semântica, que é o significado de cada instrução. Assim, um mesmo problema pode ser resolvido em várias linguagens, cada uma com seu estilo.

Para chegar até as linguagens modernas, porém, os computadores passaram por várias etapas. Por isso, vale voltar ao início da programação.

O início da programação

Os primeiros computadores eram construídos com válvulas, que depois deram lugar aos transistores. A cada novo programa, era preciso reprogramar a máquina reposicionando fisicamente seus elementos.

Essa programação manual corresponde ao que entendemos como nível 0, ou nível de lógica digital. Os computadores dessa época eram enormes, gastavam muita energia e tinham baixíssima capacidade de processamento, se comparados aos atuais.

A primeira linguagem de programação

O próximo estágio da programação é o nível 1, ou nível de microprogramação. Nesse ponto, os computadores passaram a entender uma linguagem muito simples, formada por apenas dois símbolos.

O 0 indica baixa ou nenhuma presença de energia em um circuito, enquanto o 1 indica presença de energia. A partir dessas combinações, a máquina realiza pequenas tarefas pré-programadas.

Como é a única linguagem que o processador realmente entende, ela ficou conhecida como linguagem de máquina. Todas as outras linguagens de programação, cedo ou tarde, precisam chegar até ela.

Como curiosidade, um "olá mundo", como costumamos ver nos exercícios iniciais, fica assim quando representamos cada caractere em binário.

01101111 01101100 11100001 00100000 01101101 01110101 01101110 01100100 01101111

Cada grupo de oito bits corresponde a um caractere na codificação Latin-1, incluindo o espaço e o "á". Vale notar, no entanto, que isso é o texto em binário, e não as instruções que fariam o processador exibi-lo na tela.

As gerações seguintes das linguagens de programação

A geração seguinte de computadores trouxe os interpretadores. Um interpretador recebe instruções mais simples e menos específicas e, como o nome sugere, as interpreta, executando as ações equivalentes no nível de máquina.

Os interpretadores facilitaram muito o surgimento de novas linguagens de programação e também dos sistemas operacionais. A partir daqui, passamos a classificar as linguagens como de baixo nível ou de alto nível.

Quanto mais próxima do nível da máquina, mais explícitas precisam ser as instruções. Por outro lado, quanto mais próxima do usuário, mais abstratas e simples elas podem ser.

Linguagens de programação de baixo e alto nível

A distinção entre baixo e alto nível é uma das primeiras classificações que você encontra ao estudar linguagens de programação. Ela indica o quanto a linguagem se aproxima do hardware ou do ser humano.

Linguagens de baixo nível

Linguagens de programação de baixo nível são aquelas muito próximas do nível de máquina. Elas exigem instruções detalhadas sobre o que fazer e como fazer, o que as torna mais difíceis.

Por esse motivo, essas linguagens não são as mais indicadas para quem está começando agora no mundo da programação. Ainda assim, aparecem em drivers, sistemas embarcados e trechos críticos de desempenho.

Linguagens de alto nível

As linguagens de alto nível são abstratas e facilitam o trabalho de quem as utiliza. Elas rodam em um nível mais próximo do usuário do que da máquina.

Isso significa que entender e desenvolver com elas fica mais simples. Em contrapartida, o código precisa passar por algumas etapas antes de chegar ao hardware na forma de instruções executáveis.

Existem várias linguagens de programação com propósitos diferentes. Algumas precisam traduzir o código para linguagem de máquina antes da execução, e por isso recebem o nome de linguagens compiladas.

Outras dispensam essa etapa explícita de tradução e são executadas diretamente por um programa intermediário. Chamamos essas de linguagens interpretadas.

Diagrama em camadas mostrando os níveis das linguagens de programação, da lógica digital do hardware até as linguagens de alto nível
Cada camada abstrai a anterior, aproximando o código da forma como as pessoas pensam.

O que são compiladores

Compiladores são, essencialmente, tradutores. Eles convertem o código escrito na linguagem de origem em outra forma, geralmente código de máquina.

Existem diversas categorias de compiladores, mas aqui nos concentramos no conceito. Antes de traduzir, o compilador analisa o código de origem, reconhece sua estrutura e verifica se ele segue as regras da linguagem.

Essa análise acontece em fases. Primeiro, o compilador separa o texto em palavras e símbolos; em seguida, monta a estrutura do programa e, por fim, gera o código de destino.

Ilustração de um arquivo de código-fonte sendo convertido pelo compilador em código binário
O compilador recebe o código-fonte e entrega uma versão que a máquina consegue executar.

Como o processo acontece antes da execução, muitos erros aparecem ainda no momento da compilação. Dessa forma, o desenvolvedor corrige problemas antes que eles cheguem ao usuário final.

Linguagens de programação interpretadas

As linguagens de programação interpretadas são aquelas que o interpretador lê e executa no momento da execução. Ou seja, você roda o arquivo de código diretamente, sem gerar antes um executável.

O glossário oficial do Python resume bem a troca envolvida. Linguagens interpretadas costumam ter um ciclo de desenvolvimento e depuração mais curto, embora seus programas geralmente rodem mais devagar.

Elas também têm distribuição simples. Se você publica um código com erro, basta substituir o arquivo e a correção já passa a valer.

Porém, exatamente por não passarem por uma compilação prévia, identificar erros fica mais difícil. Muitos problemas só aparecem quando o trecho com defeito é executado.

Linguagens de programação compiladas

As linguagens de programação compiladas não contam com a mesma facilidade de execução das interpretadas e dependem de um compilador. Antes de rodar, o código passa por uma etapa de tradução completa.

Em compensação, a compilação traz a análise do código, o que permite tratar erros antes que o resultado chegue ao usuário final. Além disso, o programa gerado costuma ter um desempenho melhor.

Na prática, a fronteira entre os dois grupos ficou mais difusa. Várias linguagens modernas compilam para um código intermediário e depois executam esse código em uma máquina virtual, como veremos em Java, Python e C#.

Linguagens tipadas e não tipadas

Algumas linguagens exigem que cada variável tenha um tipo de dado declarado e verificado antes da execução. Chamamos essas linguagens de estaticamente tipadas, e é comum ouvir também o termo fortemente tipadas.

Nelas, ao criar uma variável, especificamos seu tipo, como inteiro, cadeia de caracteres ou número de ponto flutuante. Essa característica dá menos liberdade, mas permite otimizar a alocação de memória e detectar erros cedo.

Veja um exemplo de dados tipados em C#.

int age = 18;  // OK
age = 18.11;   // ERRO: não é possível converter double para int
age = "18";    // ERRO: não é possível converter string para int

Já nas linguagens que costumamos chamar de não tipadas, declaramos variáveis sem definir o tipo. O termo mais preciso é dinamicamente tipadas, porque os valores têm tipo, mas a variável pode mudar de tipo durante a execução.

Veja o mesmo exemplo em JavaScript.

let age = 18;   // OK
age = 18.11;    // OK
age = "18";     // OK

Repare que reatribuímos a mesma variável. Segundo a documentação do let no MDN, declarar let age duas vezes no mesmo escopo gera um SyntaxError.

Em JavaScript, o motor da linguagem descobre o tipo de cada valor em tempo de execução. Por isso, a flexibilidade é maior, mas alguns erros só aparecem quando o código roda.

Linguagens de código gerenciado

Linguagens de programação de código gerenciado dependem de um ambiente de execução, conhecido como runtime. Aqui no balta.io, usamos o C#, que roda sobre o CLR (Common Language Runtime).

De acordo com a documentação sobre código gerenciado, o compilador do C# gera uma linguagem intermediária chamada IL. Em seguida, o CLR converte essa IL em código de máquina com o compilador JIT (just-in-time).

Esses ambientes também cuidam de segurança e alocação de memória. Assim, nossas interações diretas com os recursos da máquina diminuem e podemos focar no desenvolvimento das funcionalidades do software.

O coletor de lixo é um bom exemplo disso, porque libera automaticamente objetos que não estão mais em uso. Para entender o mecanismo, leia o artigo sobre o garbage collector em C#.

Quais são as principais linguagens de programação

Segundo a pesquisa anual do Stack Overflow de 2020, JavaScript, Python, Java e C# estavam entre as linguagens de programação mais usadas naquele ano.

Com base nessas linguagens, vamos desenvolver um pequeno programa que exibe uma mensagem na tela ou no console. Assim, você compara a sintaxe de cada uma lado a lado.

Se ainda está em dúvida sobre por onde começar, o artigo além do código: qual linguagem devo aprender ajuda a pensar na escolha com mais critério.

Hello World em diferentes linguagens de programação

O "Hello World!" é uma tradição quando começamos a aprender uma nova linguagem. Falamos um pouco sobre isso no artigo como programar, que aborda os primeiros passos na área.

Para imprimir esse pequeno texto, cada linguagem tem a sua forma. A seguir, veja os exemplos.

JavaScript

O JavaScript é uma linguagem dinamicamente tipada e interpretada pelo motor do navegador. Para executar o nosso "Hello World!", basta abrir o navegador e acessar o console de desenvolvedor.

Na maioria dos navegadores, aperte F12 e selecione a aba Console.

Ferramentas de desenvolvedor do navegador abertas com a aba Console selecionada
O console do navegador permite testar código JavaScript sem instalar nada.

Em seguida, digite o código abaixo.

alert('Hello, World!');

Ao apertar Enter, uma pequena janela pop-up aparece com o texto digitado. Se quiser ir além, o artigo o que é JavaScript apresenta a linguagem com mais detalhes.

Para os próximos exemplos, usaremos a ferramenta online Ideone. Nela, basta selecionar a linguagem no rodapé do editor e escrever o código equivalente.

Python

O Python é uma linguagem interpretada, de tipagem forte e dinâmica. Isso quer dizer que o tipo da variável é definido durante a execução, e que a linguagem não converte tipos incompatíveis de forma silenciosa.

Antes de executar, o Python compila o código-fonte para bytecode, uma representação intermediária. Depois, uma máquina virtual executa esse bytecode, e por isso a distinção entre interpretada e compilada fica nebulosa, como admite a própria documentação.

print("Hello, World!")

Java

O Java é uma linguagem compilada e, ao mesmo tempo, interpretada. O compilador transforma o código-fonte em bytecode, uma linguagem intermediária que a JVM (Java Virtual Machine) executa.

Como existe uma etapa de compilação explícita antes da execução, costumamos classificar o Java como linguagem compilada.

import java.io.*;

class Example
{
    public static void main(String[] args)
    {
        System.out.print("Hello, World!");
    }
}

Ao clicar em Run no Ideone, o código é compilado e executado, e a saída aparece na página carregada automaticamente.

O que é o C#

O C# é uma linguagem de programação orientada a objetos, compilada e gerenciada. Ela também é fortemente tipada, faz parte do ecossistema da Microsoft e serve para desenvolvimento de propósito geral.

Durante a compilação, o C# gera uma linguagem intermediária, assim como o Java. Em seguida, o .NET executa esse código, e por isso classificamos o C# como linguagem compilada.

Com C#, você desenvolve aplicações web, desktop, jogos e também mobile. Além de completa, ela é uma linguagem madura, com documentação robusta e uma comunidade grande.

Em relação ao mercado, grandes empresas usam C# em seus sistemas. Portanto, trata-se de uma linguagem com boas oportunidades de trabalho, como mostra o artigo sobre C#.

C# como sua primeira entre as linguagens de programação

Antes de tudo, precisamos reconhecer que C# não é a linguagem mais fácil entre as linguagens de programação. Existem opções mais simples, assim como outras mais difíceis, como C.

Porém, por ser orientada a objetos, ela ensina a programação orientada a objetos desde o início. Assim, você desenvolve uma base sólida logo nos primeiros passos.

Aprender o básico com C# também prepara você para futuras linguagens de programação. Dessa forma, você amplia seu conhecimento e evita voltar depois para estudar esses fundamentos.

Para conhecer os pilares desse paradigma, vale ler o artigo sobre orientação a objetos.

Hello World em C#

O C# é uma linguagem fortemente tipada e compilada. O código abaixo segue os paradigmas da orientação a objetos e é composto por um namespace, uma classe, um método e o comando que exibe a mensagem.

namespace Article
{
    public class Example
    {
        public static void Main()
        {
            System.Console.WriteLine("Hello, World!");
        }
    }
}

Execute o código acima também no Ideone, selecionando a linguagem C#. Com isso, você vê na prática a diferença de estrutura em relação ao Python e ao JavaScript.

Conclusão

Linguagens de programação evoluíram de válvulas e combinações de zeros e uns até ferramentas abstratas, que aproximam o código do raciocínio humano. Entender essa trajetória ajuda a perceber por que cada linguagem funciona de um jeito.

Compiladas ou interpretadas, estáticas ou dinâmicas, gerenciadas ou não, todas as linguagens de programação cumprem o mesmo papel. Elas transformam ideias em instruções que a máquina consegue executar.

Agora que você conhece os conceitos principais, escolha uma linguagem e escreva seu primeiro programa. Se a escolha for o C#, o curso Fundamentos do C# do balta.io é um ótimo ponto de partida.

FAQ

O que é uma linguagem de programação?

É um conjunto de regras, palavras e símbolos que permite escrever instruções para o computador executar. Ela faz a ponte entre o raciocínio humano e a linguagem de máquina.

Qual a diferença entre linguagem compilada e interpretada?

A compilada passa por uma tradução completa antes da execução, enquanto a interpretada roda diretamente por meio de um interpretador. Muitas linguagens modernas combinam as duas abordagens.

JavaScript é uma linguagem sem tipos?

Não exatamente, porque os valores em JavaScript têm tipos. O termo correto é dinamicamente tipada, já que a variável pode receber valores de tipos diferentes.

O que significa código gerenciado?

É o código executado por um runtime, como o CLR do .NET, que cuida de memória e segurança. O C# é um exemplo de linguagem de código gerenciado.

C# é uma boa primeira linguagem?

Sim, embora não seja a mais fácil, ela ensina orientação a objetos e tipagem desde o início. Essa base facilita o aprendizado de outras linguagens.

Glossário

Termo Significado
Bytecode Código intermediário gerado a partir do código-fonte e executado por uma máquina virtual.
CLR Common Language Runtime, ambiente de execução do .NET que gerencia memória e execução.
Compilador Programa que traduz o código-fonte para outra forma, geralmente código de máquina.
Interpretador Programa que lê e executa o código-fonte sem gerar antes um executável.
JIT Compilação just-in-time, que converte código intermediário em código de máquina durante a execução.
JVM Java Virtual Machine, máquina virtual que executa o bytecode Java.
Linguagem de máquina Conjunto de instruções binárias que o processador executa diretamente.
Tipagem dinâmica Modelo em que o tipo da variável é definido durante a execução.
Tipagem estática Modelo em que o tipo da variável é definido e verificado antes da execução.

Fontes