Hello World Como Você Nunca Viu! | Entendendo C

251.8k views12171 WordsCopy TextShare
Fabio Akita
Se você nunca viu C ou como um programa funciona de verdade no baixo nível, hoje é sua chance de ver...
Video Transcript:
o Olá pessoal Fabio Akita seguindo meus Episódios com o tema de fita de bits que vem explicando desde os episódios de introdução à computação até a história de turnê vão Norma no penúltimo episódio eu expliquei sobre a diferença entre arquivos binários e executáveis como os de formato Elf e os arquivos texto e como tudo são fitas debito.ou que eu chamei de linguiça hão-de bits e hoje eu quero tentar explicar como podemos representar dados e manipular bits nessa língua e Sona para vocês conseguir enxergar um pouco melhor como linguagens de programação lidam com dados se você
for em directo aprender uma linguagem de alto nível como o pai então hoje a bicycle pç sem ter aprendido linguagens de baixo nível vai eternamente ter dúvidas de O que exatamente a linguagem tá fazendo porque certos comportamentos estranhos acontecem do nada eu aprendi programação no começo dos anos 90 com linguagens de alto nível também no caso foi base e depois de base Eu só fui entender como as coisas funcionavam quando eu comecei a estudar ciências da computação É muita gente resolveu pular essa etapa E por isso vai ficar travado muito em breve e no vídeo
de hoje eu quero tentar abrir as portas para coisas que você raramente vai encontrar não curso qualquer por aí infelizmente é impossível eu resumi anos de Ciências da Computação num vídeo só então você vai precisar complementar o que eu disser hoje com a ajuda do seu professor da faculdade ou pelo menos alguém mais experiente que você aliás eu sei que tem vários professores que assistem os vídeos então este é um episódio onde seus alunos vão precisar de ajuda eu fiquei indagando se eu devia quebrar esse episódio em duas ou três mais eu resolvi puxar tudo
em um só mesmo para tirar isso do caminho de uma vez Então eu já aviso que vai ser super denso e bem difícil mesmo se você for iniciante é normal não entender tudo só assistindo uma vez mesmo se você já sabe ser Talvez goste de rever alguns conceitos de novo e até ajudar o povo nos comentários com tudo isso dito respirem fundo peguem papel e caneta para anotações e vamos lá E aí [Música] o objetivo de hoje é destrinchar o linguição de bits de tule e mapear o que acontece numa linguagem de programação de verdade
vamos seguir o buraco do coelho e tentar enxergar a mulher de vermelho Na Mente quiser a primeira coisa para relembrar na fita de bits a máquina de tule ou tá o programa tem tanto binários que representam instruções para sua CPU um também valores e dados tudo junto um atrás do outro por exemplo um hello world da vida vai assistir o valor hello world como uma cadeia de caracteres O que chamamos de um stringhi e junto vai ter instruções para mostrar esse stringhi na tela de alguma forma string em inglês é tipo um barbante uma corda
um fio a forma mais simples de stringhi é uma cadeia de bike terminada com Lulu descer se a gente encontrar o hello world usando ASCII utf-8 cada letra será representada por um código de 8 bits que é um baixo então serão 11 bytes de tamanho mais um no final mas se forem japonês ar ou o aro do Isso é uma os 7 símbolos cada símbolo alfabeto Katakana a ocupar três baixo então você não 21 bytes de tamanho como expliquei no episódio anterior Quantos bytes cada símbolo culpa depende da tabela de conversão entre grifos e caracteres
Esse é o encoding uma string com caracteres ocidentais de 8 bits é particularmente interessante porque é igual a uma rede by Array em inglês é tipo uma série O conjunto de coisa uma lista sequencial com cada elemento do Array um atrás do outro na memória sem buracos no meio e essa distinção é importante eu já vou voltar a falar de a raiz daqui a pouco mais antes precisamos falar de números em algumas linguagens você vai ver duas palavras distintas um byte e um scharf puxar for Ask de 8 bits então um chá é a mesma
coisa que um byte na prática como vencer mas em ser charpieu Java cada achar representa um cara que tem utf-16 que tem 16 bits 12 bairros portão download it não se pode achar que um chá é sempre e com um baixo só quando falamos de ser então como hoje eu só não pode ser um cidade unchar sendo um byte cada linguagem suporta um certo número do que chamamos de tipos primitivos shar é um exemplo de primitivo que é um pequeno pacote de bits sem metadados outro exemplo são números no mundo real estamos acostumados a pensar
em números como os inteiros indo de menos infinito até mais infinito mas em computadores os números são limitados por seus tipos e temos diversos tipos de inteiros na maioria das linguagens de programação a gente costuma lidar com inteiros de 8 16 32 ou 64 bits respectivamente em 28 2016 int32 ou int64 na linguagem um host por exemplo é exatamente assim que é dividido e eles são chamados de e 8 e 16 e 32 e em 64 e o rosto ainda tem 1 128 também um 2018 é basicamente um byte ou um chá descer no caso
de ser Sharp 2016 é chamado de o win32 é o enterro propriamente dito e enche 64 é chamado de long no caso dos e é mais complicado porque se eu não tô muito errado algum independia da arquitetura do CPU então lente não computador de 16-bits eram 2016 mas não computador de 32 bits e você recompilação mesmo programa o ente passava a ser 32 bits à primeira vista parece uma boa ideia porque assim toda vez que a CPU evolui bastaria ver como que lá o programa e ele automaticamente teria acesso a mais memória mas na prática
isso pode levar a diversos tipos de bugs inesperados Então quem decide o tamanho dos inteiros descer é o compilador mais nas linguagens mais modernas que você Sharp um host a declaração fica mais explícito qual tipo de inteiro você tá usando a razão de ter diferentes tipos de inteiros é a eficiência e você sabe que no seu programinha não vai precisar de números maiores que 255 basta colocar um 28 1 byte e vai ser suficiente se você é localmente 64 eu precisava a desperdiçar 7 bytes que não vão servir para nada se for uma variável só
não faz diferença mas se for um Array com milhares ou milhões de elementos você vai rapidamente desperdiçar megabytes ou até gigabytes à toa números inteiros ainda tem outra característica importante eles podem ser Side ou anside ou seja de sinal ou não tem sinal se declara um inteiro Ancine sem sinal Ele pode ser usado para números de 0 até ex FF que é 255 Mas se for Side pode de negativo 127 até positivo 128 quase a metade nesse caso o primeiro mítico é chamado de bit mais significativo costuma ficar esquerda dependendo do indígenas do processador é
onde vai ficar o sinal se o primeiro bit for zero então número positivo se for um então negativo daria para fazer um vídeo inteiro só falando de inteiros negativos e porque eles são interessantes nisso é uma das coisas que eu recomendo pesquisarem a respeito depois mas logo dizer o seguinte passo me trair e com sinal como 15 e 5 o computador Primeiro vai enxergar eles em binário em 8 bits no caso de 15 seria o binário 000011 no caso de cinco seria 0000010 um você já aprendeu que subtraíram o número é o mesmo que somar
com o seu negativo então poderemos usar a máquina de somar Eu já mostrei como funciona no episódio de introdução mais Hardcore a computador cerveja se não lembra mais computadores usam o que se chama de método de complemento que a ideia de fazer uma subtração virar uma soma e usar o mesmo circuito de soma para fazer isso ele transforma o segundo número no seu complemento de 2 ou tios complemente Esse é um tema que você pode perguntar para o seu professor se ele não explicou ainda para achar esse complemento é simples basta free para todos os
bicos e somar um então o número cinco que é 0000001 vai virar 1110101 mais um que é um 101 o porquê de esse um extra no final é um dos motivos para vocês e completa de to complement depois por agora vamos tomar o 15 com esse cinco negativo da direita para a esquerda vamos lá um mais um dá dois que é 10 então fica zero e sobe um agora um mais um mais um é 3 que é um erro então fica um e sobe um de novo um mais um e zero então fica zero e
sobe um de novo um mais um mais um é três então ficar longe sob um agora tá fácil um mais um fica zero e sobe um de novo um mais um fica zero e sobe um fica zero e sobe um fica zero e sobe um o último subiu a gente descarta e o que fica no final é 0000 ou seja como o primeiro bit é zero um número positivo e depois 10 10 que é oito mais dois em decimal que dá 10 exatamente 15 - 5 como você já sabia e com isso demonstramos que é
possível subtrair números inteiros com sinal usando o método de complementos em usando o mesmo circuito da máquina de somar binário a CPU são feitas de tal maneira para tirar vantagem de ser base dois enfim Ben 10 para conseguir calcular de forma mais eficiente do que fazemos com números decimais multiplicar e dividir é mais complicado e se tiver interesse estudem o algoritmo de multiplicação de Booth mas tudo isso foi só para dizer que existe diferença entre inteiros com sinal e sem sinal eu já expliquei que dentro da CPU em diversos e registradores é como se fossem
variáveis globais fixas no hardware no 6502 do nintendinho tinha o registrador a a x y e outros todos de 8 bits e quando falamos de um Intel ou AMD moderno em registradores e instruções de 64 bits Mas e quando precisamos fazer contas com números extraordinariamente grandes acima dos regras abaixo e 64 bits comportam isso não é incomum principalmente no mundo de Big Data e deixa Science para isso existem tipos compostos como o Big interior e Tecnicamente Não Tem Limites se você tentar colocar um número de 128 bits um registrador de 64-bits Vai dar overflow ou
seja e daí esse número seria trocado em metade seria perdido em vez disso alocamos memória RAM para guardar esse número e a grosso modo fazemos a soma com a primeira metade depois com a semana metade concatenarmos o resultado e sim você pode fazer a soma de um número grande com duas soma de números menores basta carregar o Keri Beach para segundo a soma então precisaria de pelo menos duas instruções de adição numa máquina de 64 bits para somar dois e interiores de 128 bits Mas é possível só vai custar pelo menos duas vezes mais caro
do que são números menores 64 bits tudo em computação tem um custo não é automático nem tudo igual dito isso eu falei um monte de nomes que podem parecer complicado mas só precisa lembrar que são Convenções de como representar números inteiros decimais em formato binário com limites que vão De 8 até 64 bits dependendo da arquitetura na ativa da CPU ou mais se usarmos Abstrações como Big impede e com esses números podemos fazer Olá tudo que precisamos aliás pense que a geração de microcomputadores de 8 e 16 bits foi quase inteira baseada só em números
inteiros todo joguinho de nintendinho até Mega Drive é feito usando números inteiros a tela de um jogo tem 320 colunas por 240 linhas de resolução que é um número inteiro o Sprite de entende tem 8 por 8 pixels 18 por 16 pixels para mover um Sprite de lugar basta isso mando de um em um pixel os Sprites podem escolher entre paletas de quatro cores dentre 54 disponíveis pontuação de jogos quantidade de vidas número de fase é tudo números inteiros e fora dos games em aplicativos de produtividade seja planilhas processadores de texto tudo é baseado em
números inteiros quantidade de letras ou palavras no texto é um número inteiro mesmo se você mexer com coisas com preços que tem frações da moeda em centavos basta multiplicar por 100 e fazer contas com empresas e só no final dividir por 100 e trocar com duas casas decimais então preços de produtos salários impostos tudo pode ser calculado facilmente e mais importante rápido porque um hardware tem circuito para somar números inteiros foi principalmente com o advento de coisas como computação gráfica animação em 3D que números fracionados começaram a fazer diferença no mundo comercial e claro da
Computação científica já precisavam fazer cálculos fracionados com muita precisão em previsões de meteorologia o laboratório Mas isso é em nichos mais isolados e restritos um acesso a hardware especializado desde o começo do século 20 já tinham formas de calcular números fracionados oz1d Conrad Zuza que Eu mencionei na história de Turim e vão nome já tinha esses conceitos inclusive seus e quatro foi o primeiro computador comercial nos anos 1940 até suporte a números fracionados many friends como o univac os da IBM dos anos 60 tinham suporte a calcular números fracionados também mas foi só quando começamos
a adotar take 12 bits no começo dos anos 80 que os diversos padrões começaram a convergir para o que viria a se tornar o padrão ee754 e só a partir do meio dos anos 80 que começamos a adotar em micro computadores domésticos no CPU de 8 bits como o 8086 a Intel começou a desenvolver o que você chamaria de coprocessadores matemáticos como 8087 até a era do 386 a gente tinha opção de adicionar um segundo chip como um 8387 que custava caro para caramba tem que os programas usavam não lembro se foi já a partir
dos 486 ou só uns prints E paramos de precisar de coprocessadores porque as instruções passaram a vida a própria CPU precisamos entender para que serviram esses com processadores eu disse que até agora estávamos indo bem com números inteiros só o CPU dos anos 80 era um bom sem processar números inteiros mas eventualmente a gente precisa lidar com números fracionados com decimais em particular números irracionais ou seja o que não podem ser representados Com uma fração de números inteiros raiz quadrada de dois número pi e muito mais o PI é o inteiro três Depois tem uma,
e começam a cadeia infinita de números 14159 2653 e assim vai sem padrão nenhum até o infinito se um número com decimais pode ser representado por uma fração podemos usar números inteiros por exemplo o número 0,333333 a de infinito é o inteiro um dividido por inteiro três Assim muitos números com casas decimais infinitas podem ser representados claramente com números inteiros finitos mas o mesmo não acontece com números irracionais com o pi e computadores não tem memória infinita Então não temos como representar perfeito daí Precisamos de uma aproximação e a palavra importante aqui é aproximação O
que significa que ele não vai ser armazenado na memória como você acha que deveria e sem algo perto disso essa aproximação é a especificação e 7 eu acho que define chamamos de ponto flutuante esse tema é super chatinho levaria um curso inteiro para explicar e mesmo assim você vai ter dificuldade de entender então eu vou simplificar grosseiramente hoje agora a pouco eu expliquei como podemos ter inteiros com sinal e sem sinal e quando tem sinal reservamos o primeiro bit mais significativo para ser o sinal se for zera positivo se for uma negativo mas podemos reservar
mais bits para outras coisas também bits são que a gente quiser que elas sejam em países como Brasil as casas decimais são separadas por, mais nos Estados Unidos em outros lugares se usa ponto em vez de, por isso falamos em ponto flutuante e não, flutuante você já deve ter ouvido falar do tipo flaut o ponto separa a parte inteira do número da parte decimal e no computador fazemos esse ponto flutuar para aumentar ou diminuir a precisão Mas isso não é história toda we 754 definir vários tipos de flores mais conhecido hoje o bar 14 tem
o número de 64 bits ou quatro bairros o primeiro bit é igual de um inteiro com sinal Ele define o sinal depois vem 11 bits que representam o número do expoente e os demais 52 bits representam a mantissa e o que que é isso é a notação científica mas da base dois na base 10 para representar o número como 15.000 poderia ser um ponto 5 x 10 elevado a 4 ou 1.5 e quatro e esse é de expoente 1.5 a mantissa quatro é o expoente na base 10 11 front é a mesma coisa só que
seria o primeiro bit de sinal para positivo negativo daí dois elevado ao expoente armazenados nos próximos 11 bits multiplicado pelo número representado nos 15 minutos seguintes que a mantissa o número inteiro o máximo que pode ser representado nesse formato é 2 elevado a 53 que dá o número 9 quadrilhões e tralala que em particular se você é java script é o que você já conhece como Max save e interior que em binário é representado assim aqui do lado Zé é para ser positivo o expoente só com o último vídeo gripado e a mantissa inteira de
um da mesma forma o que eu já me esqueci de você chama de mim Safe entende o mínimo que é o menor número que se pode representar sem é sofre parou inverter todos os bichos do expoente e o primeiro bico significativo do sinal que temos 19 quadrilhões e trolla lá no negativo O Grande Lance é que não conseguimos representar em notação científica de base dois exatamente o número que normalmente queremos de decimal sempre vai ter um errinho de conversão por exemplo podemos ir no site que está linkado abaixo nas descrições que mostra essa conversão para
a Gente Se tentarmos converter 0.1 na realidade vai dar 0.10000 7 Vezes 149 etc que é esse binário aqui do lado é uma aproximação na base dois ou seja depois de um vai ter uma pequena sujeira por isso Tecnicamente é diferente de 0.10000 exato embora bem próximo se arredondar mesma Como converter 0.2 em binário vai virar 0.200 7 Vezes de novo 298 etc e esse número fosse em binário esse outro número são aqui do lado e para finalizar 0.10.2 devia ser 0.3 exato se fosse base dois mas é no ponto 3 em binário vai ser
esse número são aqui do lado com o erro de conversão na verdade vai ser 0.300 6 x 19 27 sempre vai sobrar uma freirinha em vez de ser 0000 se somarmos 10.10.2 na instrução de soma binária do CPU com os erros de precisão dessas conversões seminário O resultado vai ser 0.30 007 x depois 447 etc mas a conversão do 0.3 para fonte da 0.300 só seis vezes em vez de sete e depois um e não 44 é por isso que ele já vi escrito tinha diversas outras linguagens como o pai se você fizer 0.10.2 tem
10.3 vai dar falsa Porque de fato quando converter de decimal para fonte na base dois ele vai ganhar essa sujeirinhas de um de precisão na conversão e quando se faz conta Quais as previsões ligeiramente erradas a precisão do resultado também vai ser ligeiramente errado quem já tentou fazer muitas contas conflat já se deparou com isso e para ser justo não é só em javscript que você fizer comparação exame. Mas era o ponto 2.0.3 vai encontrar aqui é falso em um Hub em Rust in Python Se não me engano ser Sharp é uma linguagem que se
dá ao trabalho de ajustar esse erro de precisão e devolve verdadeiro mas no resto e só faz a conversão direta para Bayern em 64 2754 vai ter esse problema nada intuitivo se você só pensar na base 10 e não na base dois você faz zero. Mais zero. Dois e no final não é exatamente 0.3 isso é pior no java script por outra razão em JavaScript único tipo numérico que existe é o Font Bayern e 64 não existem inteiros primitivos como monstro antes então em vez o máximo de 2 elevado a 64 Março vai ser dois
elevado a 53 Como declarado no tal Max save entender que é um número grande mas não é o máximo que só que tudo suporta e se você quiser conta com dinheiro tipo desconto em produtos calcular saldo baseado no extrato de conta não faça confronto porque esse erro de precisão uma hora vai dar ruim pequenas sujeiras de precisão em grande volume de contas uma hora vai afetar bastante no mínimo multiplique o valor por 100 para trabalhar com centavos ou truque depois de duas casas para não ter essa sujeira no final melhor ainda justamente por conta de
bugs de precisão como esse existe outros tipos de dado semelhante ao Big interior que eu falei antes a maioria das linguagens tem um tipo chamado Big décimo assim como o Big interior para fazer contas aritméticas vai ser mais lento porque vai precisar quebrar o número em segmentos fazer aritmética das partes e depois dá um jeito de concatenar o resultado porque o número não não cabe não seja extratores de 64 bits no caso do Big décima mesma coisa ele com mais precisão e cuidar para evitar essa sujeira de conversão a linguagem Java script não tem um
big décimo nativo Então você precisa baixar uma biblioteca que ofereça isso na verdade Esse é um dos pontos onde java script é corretamente criticado ou do número nele seja o inteiro ou seja um forte em binário é representado como um flute by nele 64 que eu pessoalmente acho Tosco existe uma classe Number e ela deveria converter os tipos corretos internamente até para pesar menos toda vez que precisa fazer cálculos dependendo de que versão da história você ver esse é um dos efeitos colaterais da linguagem tem sido criada tão às pressas e depois que já foi
adotado assim você tem dificuldade de voltar atrás depois pesquise sobre isso enfim o flute que a maioria das linguagens usa é o tal binary 64 64 bits que eu expliquei mas antigamente o que era chamada de front-ends e ela versão Bayern de 32 e a versão 64 bits era chamada de Dragon Ball então se algum dia você vê dando é o flush the system e de qualquer forma o importante era explicar que existe essa forma de representar números e existem outras compra representar os números complexos mas não é importante para hoje Lógico que fica de
lição de casa para vocês depois agora vamos voltar ao tal do Array Array é um conjunto que contém elementos do mesmo tipo sequencialmente um atrás do outro na fita de bico como por exemplo a rede números 28 ou front quando associamos uma variável a uma Rei na realidade estão apontando para o endereço do primeiro elemento desse Arreio e toda vez que tentamos acessar uma posição específica dentro desse Array basta pegar o endereço inicial de somar pelo tamanho do tipo do elemento que ele contém o importante de arrays Strings é entender que a sequência de bytes
ou Charles é necessariamente um atrás do outro sem intervalos no meio a gente coloca um stream de 100 caracteres shared um byte tamanho o Array vai usar 101 bytes de memória contigo esse uma mais é o Buzz o final da sequência que indica o término dela no caso de Strings a beleza e que para acessar qualquer elemento dessa sequência sabendo a posição basta pegar o endereço do primeiro elemento o comprimento de cada elemento no caso um baita e multiplicar pela posição para ser o endereço do que estamos procurando no exemplo do hello world é uma
rede charge de 12 baixo contando o no final se eu quiser puxar a sétima letra basta pegar o endereço do primeiro elemento que é o h do Hello e somar por sete bikes já que cada achar tem um baile comprimento e nesse certinho o endereço vai estar a letra w the world como esperado agora isso só funciona porque cada elemento tem exatamente o mesmo comprimento a mesma quantidade de bits o requerimento de todo o Array aqui todos os elementos dentro devem ser do mesmo tipo Se quisermos armazenar números long que tem 4 bytes então todos
os outros elementos precisam ser long da em uma rede sem elementos long vai ter 400 bytes e em um outro problema disso é que uma rede tem tamanho fixo uma vez alocado não tem como ser expandido Daí você pode ficar confuso porque não java script outras linguagens se o a reiniciar o tem sem elementos e eu quiser adicionar mais um basta acessar direto uma posição 101 e escrever lá por exemplo um abrir o console java script em qualquer navegador e declarar um Array chamado lista com as 5 letras como o nosso Hello Se eu tentar
acessar a posição quatro vão pegar a última letra o' e é quatro porque todo aí que se preza começa na posição zero Se eu tentar pegar a posição 5 vai virando defined porque eu passei do fim do Array Mas eu posso tranquilamente gravar uma nova letra como exclamação nessa posição e um o Array automaticamente expandir para comportar a nova letra Mas como isso é possível se eu falei que a reis ele tem tamanho fixo na maioria das linguagens mais alto nível que ser tem estratégias do grego strategia ir se eu não disser o tamanho exato
que eu quero ela e colocar um espaço maior do que eu preciso dessa forma que eu precisar de mais elementos depois do fim tem espaço livre sobrando e é uma estratégia quando você sabe que tem mais rom do que precisa mas se eu realmente chegar ao fim do espaço que a linguagem alocou para o meu rei o que ela vai fazer é louca um novo Array maior copia elemento a elemento para o novo Array e descartar o antigo de novo você não tá sabendo mas está acontecendo um custo extra de processamento por baixo dos panos
no dia a dia você nem percebe porque normalmente mexe um pouco Sá Reis mas é operações que tem um milhares ou milhões aí você vai querer tomar mais cuidado com operações que fique mudando o tamanho dos Reis mesmo que a operação a linguagem seja só uma linha por baixo dos panos ela vai fazer diversas outras Como duplicar seu Array que você nem fica sabendo E aí não entendi porque a performance ficou tão ruim sem motivo aparente mais ou menos a mesma coisa acontece com Strings no cês em bibliotecas extras um está a literalmente declarados ó
como uma rede chars em linguagens mais modernas o string em um tipo separado do Array mas internamente a maioria usa-a Reis só que o tipo Extra dar um suporte maior a coisas com conversão de in Cold em tudo mais na prática tanto a responde Strings uma vez declarados e preenchidos são fixos e aumentar o tamanho deles pode envolver criar um novo Array e copiar o conteúdo do antigo em cima do novo por isso um Java tem classes estas como streambuffer para lidar com Strings se você vai precisar crescer depois agora tudo isso que eu vim
falando até agora a restringe em soufflot todos ocupam algum lugar numa memória seja hum com SSD se ou qualquer outra coisa é tudo uma fita de bits onde cada posição tem o endereço 012 e assim vai cada valor em uso pode ser encontrado nessa fita com o endereço a localização no conceito importante aqui entender que tudo tem o endereço nessa fita que pode ser qualquer a memória Pode parecer complicado só porque endereço sem máquina 64 bits podem ir até número ções do tamanho de ex abaixo E para piorar escrevemos esses endereços como hexadecimais mais Endereços
é só isso números eu sei que eu tô andando bem rápido já soltei bastante coisa até agora mas se segurem que agora que a coisa vai ficar interessante eu recomendo que depois assistam tudo de novo com calma se está novo para vocês mas agora é uma boa hora para eu descer mais ainda na escovação de bits uma coisa que eu não é claro para iniciantes é onde ficam todas essas variáveis ao longo da execução de um programa Então vamos partir de um exemplo bem besta em ser e Não se preocupem se você nunca usou ser
mesmo assim você deve ser capaz de acompanhar em outros episódios Eu já mostrei mais ou menos como isso funciona a gente abre o editor de texto escreve o código Zinho em si e uso compilador CC que é o GC para ler esse código e da out ou sai dando um binário executável em formato elf e o Linux a entender e executar você não sabe o que é isso pelo menos assistir o episódio da diferença de arquivos binário e texto onde eu mostro como isso funciona o binário é often o endereço específico Onde fica a primeira
instrução que vai começar a executar no caso é o hexa 1000 esse endereço é gravado no registrador chamado PC que é o programa Country ou contador de programa é a partir disso que eu vai executando a instrução que tá nesse contador uma vez executada a instrução incrementam o endereço do computador e aponta para próxima instrução na fita de bits bem a grosso modo só para ficar mais fácil de explicar é como se esses números fossem os números da linha do código C no nosso editor de textos Claro que não É porque o que tá no
binário não é o código que digitamos e sim o que o compilador traduzir para linguagem de máquina o linguição de bits mais para facilitar a explicação pensa que não tá o endereço 1000 ele pula ou da jump para o endereço da função Man dos e e vai executando um de cada vez nessa função sempre que eu me referia endereço de programa como sendo o número da linha é só uma metáfora para o endereço a casa decimal da instrução equivalente na memória de verdade a função Man é o ponto de partida de qualquer programa em ser
nesse exemplo vai colocar uma string hello world Daí pegamos a referência dessa variável com esse e comercial na frente Isso pega o endereço onde stringueta armazenado na memória para podermos imprimir na tela daí passamos a variável para outra função e vamos chamar de F1 e colocar no começo do arquivo aqui parece qualquer outra linguagem que você já usou chamando uma função e passando um argumento entre parentes e precisamos declarar a função é filme Antes da Man porque em ser para usar uma função embaixo ela precisa estar definida antes em outras linguagens isso não é verdade
depende do compilador mais no caso de ser assim daí nessa função F1 vamos receber como argumento uma rede Charles de novo e dentro bom imprimir o endereço onde a vale o documento foi armazenado na memória e depois repassar essa variável para outra função f 2 de novo definimos acima a função f 2 que mesma coisa vai receber um argumento de Harris deixar se imprimir o endereço da variável e por último imprimir o valor da variável O que é o hello world é um exemplo super besta só fomos passando o mesmo valor algumas funções para frente
vamos sair do editor agora e usar G CC ou CC para compilar esse código não está o executável é o fi que podemos contar agora a gente vê primeiro o endereço da primeira vez que declaramos a variável Hello na função Man e vou repetir caso tenha ficado confuso seu depende chefe direto na variável Helloween de imprimir o valor Hello Word mas como colocamos esse e comercial na frente da variável na realidade ele vai acessar o endereço onde Hello hoje está gravado na memória tudo tem o endereço e esse diferente de outras linguagens temos acesso direto
a esse endereço com essa lotação Eu já falei do endereço de cada instrução do a e na mesma memória tão valores que vamos criando como essa stringhi então executar um programa é executar a instrução em algum endereço e os valores que cada instrução vai usar por sua vez também então em algum endereço na memória e com esse e comercial na frente da variável podemos forçar o endereço pense no Hello Word como o conteúdo de um arquivo texto e esse endereço como sendo uma url de uma página Web tipo http://hello.com o segundo número são que aparece
é o endereço do argumento de dentro da função F1 quando passamos um Hello para ela veja que o endereço é diferente apesar do valor ser o mesmo ou seja ao passar variável para função ela foi duplicada e a terceira linha é a mesma coisa outro endereço diferente que foi impresso de dentro da função f 2 porque quando a f-1 passou só variável para F2 como argumento essa variável foi duplicada de novo no final queremos três cópias de cisteína memória ao longo a cada uma com endereços diferentes você pode ver que toda vez que damos print
F passando a referência da variável ela imprime um número diferente toda vez que se passa uma variável de tipo primitivo como argumento de uma função ela é duplicada nisso não é só em ser mas na maioria das linguagens isso tem um nome se chama passagem por valor que é diferente de passagem por referência que eu vou mostrar já já a vantagem é que se a gente modificar o valor do argumento dentro da função por exemplo F1 o valor original antes de ser duplicada por exemplo a função nem não vai mudar depois que a f-1 de
retorne outro detalhe o endereço é impresso negativo na tela porque o binário desse endereço começa com um e a função printf interpreta como sendo o interior com sinal e como expliquei agora a pouco se começa com um Ele acha que é um número negativo mas também por começar com um sabemos que se trata de um endereço na metade mais alta dos endereços da memória considere que o endereço mais baixo é homem 1000 64x e vai incrementando de 1 até o endereço um 64 vezes que é o endereço mais alto o espaço de memória aqui um
programa enxerga é segmentado segundo alguma convenção para facilitar a vida no Windows da vida ele começa a louca memória para drivers e coisa do sistema operacional na metade Alta ou seja começa no endereço binário 11 etc ou ex afff etc e vai diminuindo já programas de usuário só navegador Spotify e tals começa no início da metade baixa mais próximo dos endereço começam com 10000 e um adendo um computador antigo de 32 bits suportavam o máximo de Ram de 2 elevado a 32 que é pouco mais de 4GB quando passamos a adotar arquitetura 64-bits não dobramos
e memória mas sim e levamos ao quadrado por isso o máximo teórico é mais de 16 megabytes porém nenhum chip comercial Quem pé uai a fábrica onde fato suporta uma pia esse tanto de memória ainda internamente as instruções lidam com valores de 64 bits mas nenhuma raiva que você conseguir comprar nem usar MDF de trás do Hiper da vida costuma suportar tudo isso eles costumam ser capazes em 42 ou 48 bits de endereços em vez de 64 ou seja pouco mais de 280 terabytes que coisa para caramba Claro mas só para você saber que ainda
não chegamos bem no máximo do 64 bits em hardware comercial de qualquer forma isso é a memória real Mas como eu expliquei o Episódio de gerenciamento de memória um processo rodando enxerga memória virtual que é o sistema operacional mentindo para os nossos programas como se eles tivessem acesso a ponta memória teórica de 64 bits é o que chamamos de memória virtual dentro desse espaço virtual os endereços que começam do zero e vão subindo é o que chamamos de memória dinâmica ou chip que é para onde vai a maioria dos dados que seu programa carrega quando
você carrega um arquivo e memória e com se conecta a um servidor de Up Puxa um Jason ou quando pede dados no banco de dados tudo vai para o chip chip em inglês é um montão um amontoado repetindo lá no topo nos endereços que começam com 21 é onde fica o segmento de memória reservada para carne O que é uma área exclusiva para endereços de coisas do sistema operacional mas o próximo segmento é o que chamamos de pilha ou steck se eu não tô muito enganado todo o processo começa com pelo menos 8 MB de
memória alta reservada para estética e ela pode expandir decrementando o endereço para baixo pode consumir até uns 2 GB a chip é a mesma coisa mais do outro lado começa na memória baixa já com pelo menos 1 megabyte reservado e se precisar de mais vai incrementando o endereço para cima lembre-se que o está aqui de um nintendinho de 8 bits tinha 255 bytes só isso quero o endereço da casa decimal 0 1 0 0 até 0 1ff eu explico Para que serve essa e o episódio da introdução mais Hardcore A Computadores Mas vamos resumir usando
o exemplo do hello world que eu fiz agora eu tenho três funções amém a F1 e F2 cada uma delas a Ok espaço para duplicatas da string hello world da imprimir o endereço onde Amarelo falou cada e no final Sai fora e retorna para função que chamou ela aliás em ser Tem uma função tem como tipo de retorno um void que é tipo nada em ser então nem precisa da retorne porque não estamos retornando nenhum valor então vamos na ordem agora ao executar o binário ele pede para quer no sistema operacional aloca espaço para o
novo processo inicializar Seja lá o que ele precisa a perna vai usar o gerenciador de memória EA o mínimo necessário para o programa rodar e depois vai dando memória real para ele a medida que estou pedindo depois ele pula para a primeira função que é Amém Agora cria variável Hello que é uma rede charge com 12 bytes de tamanho isso é alocado na steck agora eu chamo a função do CE o print chefe eu não vou explicar com o print EV funciona lá vou aproveitar para explicar a mecânica dessa tal estética ou pilha toda chamada
de função começa aguardando o endereço atual de execução o que tá no tal contador de programas no nosso seu do exemplo de endereços seria o número da linha do nosso código onde chama essa função no momento que a função Man chama a função printf ele faz tipo um bookmark do contador de programa e coloca no istec Daí podemos substituir o endereço no contador de programa pelo endereço da função que tá chamando no caso o endereço para print F agora dentro da frente F vai alocar outras variáveis para de conta mas variável x y qualquer que
vão sendo colocadas na steck finalmente em imprimir na tela o que precisava e no final da ritani esse ritani começa a desempenhar o que é loucona steck até achar o último endereço que amém gravou o tal bookmark do computador de programas e da Jump ou seja oi para ela pular significa colocar de volta esse endereço mais um no contador de programa da ele pode continuar da próxima linha depois de chamar a função é mais ou menos isso que faz um retorne o que tinha sido colocado na steck pelo print aqui foi liberado e voltamos a
executar na próxima linha de volta aumente a próxima linha chama a nossa função F1 mesma coisa vamos empilhar o endereço dessa posição na steck Como eu disse antes ao passar variável hello como argumento estamos duplicando a variável Então vai empilhar essa duplicata na steck também ocupando espaço dentro de F1 vai chamar print f de novo para imprimir o endereço dessa duplicada e por isso temos valores diferentes de endereços já sabemos como isso funciona então vamos pular os detalhes de print EV para não ficar repetitivo pode assumir que empilhamos e desempenhamos print f em seguida ou
f11 vai chamar a F2 em novamente o endereço dessa linha vai ser empilhado na steck avaliar e vai ser duplicada e empilhado na steck também e de novo vamos chamar print f por fim vai ter um gitane esse ritani vai desempenhando até ver o endereço de volta a função F1 e da Jump para ela agora não é fio não tem mais nada a não ser outro Brittany Então continua desempenhando até o último endereço gravado da função Man e da Jumper de volta para ela e finalmente na mente também temos o litania agora é o último
de todos então eles sai do programa inteiro daí o sistema operacional vai fazer a limpeza da memória desse processo e Tudo Termina com sucesso a razão dessa explicação longa foi para mostrar no nível mais básico O que significa chamar funções e como variáveis são gerenciadas na steck Toda vez que você chama funções e passa argumentos para ela esse registro de execução vai ser empilhado na steck que é uma pilha pilha é uma estrutura de dados super importante em uma das mais fundamentais junto com os seus que a inglês para filas elas são É mas eu
não vou falar de que eu sou hoje pilhas temos dois tipos fifo e lifo filha que estamos usando aqui do tipo nifo ou seja last in first out então último elemento que empilhamos é o primeiro que vai ser dizer empilhado Esse é mais um tema que você precisa estudar em detalhes como a implementada e como funciona em todos os casos é uma das missões de matéria de estrutura de dados e algoritmos que qualquer faculdade ensina e mesmo se você falta de data deve estudar de qualquer forma você vai se lembrar que eu falei que essa
steck Costuma começar com o tamanho de 80 isso é bastante para programa de qualquer tamanho repetindo um jogo de nintendinho inteiro ser super Maio Zelda o Final Fantasy conseguia se virar com estaca de Melo 255 bytes isso é um quarto de um mísero megabyte estourar Essa steck é sinal de má programação E acredite não é difícil estourar a Ester e quando ela estoura seu programa tá cheia é muito mais fácil de explorar é via recursão recursão é uma função fica chamando ela mesma sem parar vamos dar um exemplo podemos fazer uma função chamada F3 com
essa aqui do lado e ela fica chamando ela mesma Além disso nessa função f-3 eu vou ficar passando o argumento Hello toda vez cada chamada S3 vai duplicar stream de hello world na steck Daí vamos imprimir o endereço que cada uma delas Está ocupando na steck para dar uma olhada no que está rolando se compilar e executar notem como os endereços seguem uma sequência decrescente um atrás do outro não são números aleatórios como eu disse a Ester que começa nos endereços mais altos depois do espaço da carga na memória à medida que vão se empilhando
nova chamada de f-3 duplicando a variável hello como argumento os endereços vão diminuindo ela vai do fim em direção ao meio da memória e no final um o programa tá cheia porque acabou a estética EA função f-3 fica chamando ela mesma infinitamente Até bater o que o sistema operacional permite no caso do Linux dá um segmentation fault esse é bem genérico Mas significa que você tentou Acessar memória que não existe ou que não te pertence' ou qualquer tipo de acesso a memória que o sistema não sabe comunidade no nosso caso por ter acabado a memória
da Ester recursão é extremamente importante na programação e você precisa garantir que uma hora essa recursão vai parar antes da estética encher existe um caso especial de recursão que não enche a estética agressivamente desse jeito e ela simplesmente vai fazer Jump de volta para algumas instruções para trás sem ficar enchendo a i-tec a cada chamada recursiva Isso se chama tem wilkerson eu vou deixar de lição de casa para vocês estudar em casa nunca tinha ouvido falar disso a maioria das boas linguagem suporta tem o recorde e isso diminui bastante os casos de estourar steck Mas
além da recursão temos outro problema nesse exemplo besta toda vez que chamamos a função f-3 recursiva passamos a string de hello world o valor ou seja duplicada cada chamada recursiva que fazemos no mínimo tá empilhando o endereço para onde tá ele vai dar Jump de volta que é o endereço de 64 bits ou 4 bytes mais a duplicata de hello world que custa 12 bike só isso São Domingos 16 bytes a cada chamada uma string idealmente deveria ser imutável ou não precisamos modificar estreou concatenar mais texto nela aí sim precisaremos fazer uma duplicata Mas se
a variável vai permanecer senti a mesma como uma constante Não devemos ficar duplicando toda vez que passamos para outra função Imagina assim vez de hello world esse strengh fosse um texto enorme uma ou mais páginas da Wikipédia ocupando um mega também 1gb em duas chamadas de função do clicando variável passando por valor e acabar steck então como fazemos vamos nos lembrar que eu falei que a i-tec é só um dos segmentos da memória Total a memória virtual total de 64 bits caberia até 16 regras a bytes de dados é um giga não é nada eu
poderia duplicar um texto de 1 Gigabyte trilhões de vezes até acabar a memória toda agora vem a parte mais complicada Vamos tentar explicar para vocês têm medo um enter ou apontador parece difícil mas o básica bem simples na real em vez de alocar espaço na steck para guardar meus Strings ou mesmo qualquer outra rede gigante Vamos colocar ela no chip eu já expliquei antes que o chip é o segmento da memória total que começa os endereços mais baixos perto de zero e cujos endereços vou incrementando repetindo enquanto os endereços da i-tec começam do endereço mais
alto e vão decrementando em direção ao Começo os da gripe começa no endereço mais baixo incrementando em direção ao fim o sistema operacional vai garantir que um não cruze os limites do outro no meio Tecnicamente os endereços da Jeep podem incrementando até o limite de não ultrapassar os endereços dos Tec entenderam quando você instanciar um objeto numa linguagem como o script Ruby já vai ser Sharp o bloco de memória que contém todos os dados do objeto ficam no chip e na estética e fica só o endereço o a referência que aponta para esse objeto que
numa arquitetura de 64-bits vai ter sempre o tamanho fixo de 4 bytes Independente de quanto a memória foi alocada para o objeto no chip o truque É simples vamos voltar o hello world em vez de alocar na steck como mover para o chip em ser precisamos incluir o cabeçalho stdm com pagar que nos dá acesso a famosa função malloc que significa Memory allocation o argumento que passamos é Quantos bytes queremos que ela reserva em um chip no caso podemos a outra função chamada size of que como o nome diz se mede o tamanho de alguma
coisa e como parâmetro para essa função passamos a variável Hello que alocamos na steck que é de 12 bits poderemos passar direto o número 12 também mais do que uma Loki vai fazer é procurar um seguimento contínuo de 12 bike no jipe e passar para o endereço que ele reservou no jipe e essa nova variável Halo 2 vai guardar o endereço que é um número de 4 bytes Então esse Hello dois é um ponteiro porque seu endereço a ponta aonde vai estar o strang na chip é só isso aqui é a coisa pode ficar mais
cabeludo ainda então preste atenção conhece endereço em mãos podemos usar outra função dos e o strcpy stream copy passando como argumentos esse endereço e a variável Hello antiga para copiar o hello world para esse novo espaço na ri-happy Essa é a única duplicata que vamos ter a partir de agora a parte importante entender que na variar mais Alô dois nós não temos a string hello world Racing o endereço o primeiro byte na ri-happy onde vão encontrar essa cópia do hello world sendo o Hello 21 ponteiro com o endereço e sabendo que cada achar da string
exatamente um byte sabendo que ela acaba quando encontramos o caractere nulo se fizermos outro ponteiro chamado Halo 3 que é Hello 2 e agora vamos ter só a palavra World Se der uns print F nela vamos compilar e vou dar para ver olha como imprimir na tela o hello world do ponteiro Hello dois estou Word do ponteiro Hello três mas a gente não criou o duplicou uma nova estrela estamos apontando para o mesmo espaço na memória só que 6 bytes mais para frente essa sim táxi ou lotação de asterisco na frente é para indicar a
linguagem aqui essa variável é um ponteiro e queremos acessar o valor gravado no chip nesse exato endereço se não colocarmos o asterisco vamos direto ver só o endereço Se colocarmos o asterisco ele traz o valor para onde esse endereço tá apontando tanto as variáveis Hello dois quanto Halo 3 parece representar um estranho e diferente mas na verdade são só endereços ou mais corretamente referências ao mesmo stringer só apontando para posições diferentes no mesmo stringer para acessar o stringency usamos* Hello dois e* Hello três sejam esse Olá sejam uma rede já que string é um caso
especial de Array a variável hello não contém o Array e sim o endereço para o primeiro elemento do Array se eu quiser pegar um elemento do meio do Array primeiro eu pego o endereço e só uma quantidade de baixo que leva o elemento que eu quero se for um Array de chars que é um stringhi onde cada achar tem um byte para pegar a cesta letra basta somar seis bikes ao primeiro endereço quando fazemos aquela notação que tem toda linguagem com braquetes ou colchetes com o número no meio a linguagem tá traduzido por baixo em
uma soma de endereço como eu mostro aqui no código é o endereço Inicial mais o tamanho de cada elemento multiplicado pela posição veja que eu tô repetindo a sua operação para tentar deixar bem claro esse funcionamento tem uma última estrutura de dados que eu quero explicar para vocês hoje como eu repeti de propósito várias vezes até agora Array são listas que tem sempre os mesmos tipos de elementos ou mais correta os elementos de mesmo tamanho se for uma string é uma rei onde cada elemento tem um vai se for um Array de inteiros de 64-bits
todo o elemento tem exatamente quatro bases e eu vi repetindo a mesma coisa sobre elementos Iguais por causa do seguinte e se eu quiser criar uma sequência onde cada elemento tem tamanhos diferentes para isso em linguagens de alto nível tipo Python existe a tupla ou tampou ou no caso de ser existe extract em conceito não são a mesma coisa mas para hoje pense que é eu vou explicar porque diferente de um Array onde cada elemento de em sequência tem o mesmo tamanho numa strict ou dupla podemos declarar tipos diferentes que vão concatenando um atrás do
outro linguição de bits por exemplo podemos declarar uma struct tirou estrutura chamada por som usa o primeiro elemento vai ser uma rede charge 10 baixo um homem curtinho o segundo elemento vai ser um monte de 8 bits 1 byte chamado Aid para ser a idade dessa pessoa e finalmente o elemento vai ser altura ou rite que vai ser o enterro também de oito minutos essa estrutura Define um tipo de dados logo chamado persson cujo tamanho Total sempre vai ser de 12 bytes agora eu posso criar uma variável que vai ser esse tipo e o cê
vai preencher os valores que vamos passar na sequência correta na fita de bico se eu fizer porção. Igual a 43 porção. Rite igual a 172 e porção. Nele igual a Fábio a cadeia de bits vai ficar exatamente a senha que essa decimal Lembrando que cada dois dígitos em hexa representa um byte começamos com o hexa 46 que a letra F daí 61 que é a daí chega uma sequência de zeros porque Fábio tem menos de 10 watts o penúltimo hexa 2B é a idade 43 e o último o hexa as é 172-a streetmix serve como
um molde que encaixa exatamente nessa sequência de bits e quebra os valores para dentro dos Campos que criamos no caso de idade altura como são inteiro de 8 bits e sabemos que podemos ter idade de 0 até 255 e alturas de no máximo 255 cm e tirando alguma raríssima exceção Tipo se você for mais alto que o Hulk isso cobre qualquer pessoa do mundo única coisa nesse trecho de código que talvez deixo você confusa é porque podemos fazer Person. And igual 43 mas não podemos fazer version tornei-me igual Fábio e em vez disso eu usei
a função que Cup stringues de duas posições da memória que essa stream copy só entenda que é assim que se faz em ser mas em outras linguagens como java script você faz Do jeito mais simples ó usar igual coisas desse tipo que linguagem de mais alto nível facilitam é o que eu chamaria de ergonomia da linguagem mas com que eu expliquei até agora você conhece os principais tipos numéricos primitivos como interiores e foltz Array de Strings e agora esse truque um campo é como se fosse um strict anônimo sem nomes ou etiquetas parecido com o
Array Aliás toda vez que o sapo numa um paixão da vida vai achar que é a mesma coisa que uma rede uma tupla é um conjunto imutável com elementos de tipos diferentes só isso uma rei é um conjunto notável de elementos do mesmo tipo para extrair os elementos de uma tampa você precisa de um molde que declara Qual o tamanho de cada elemento um molde que você parecido com o Stitch Estamos chegando no final e agora com tudo que aprendemos só falta mais um truque para vocês começarem a entender melhor como os programas funcionam vocês
meio que já devem ter entendido que funções nada mais são que sequências de instruções que ficam localizados em algum endereço na memória a CPU vai executando linha a linha e quem dita qual linha é o tal contador de programas daí quando uma função chama a outra ela primeiro faz book Mark nesse contador na steck e da jump para o endereço dessa outra função repetindo é como se cada uma dessas linhas de código ficasse no endereço na memória estamos simulando como se fossem e do código no editor de textos quando na função meio lá embaixo eu
chamo a força é filme e o compilador dos e geram o binário ele vai substituir por algo semelhante a um Jump ou mesmo gorducho em linguagens mais antigas para o endereço da linha da função f um documentário é um seu do código de como seria se você tivesse uma função chamada Jump e isso é uma das razões de Porque precisamos de compiladores ia ser chato para caramba tem que ficar lembrando o endereço de cada função que precisamos E aí a gente resolve mexer na função muda de lugar e Isso muda o endereço daí tem que
mudar todo lugar que chama esse endereço na mão um tá trampo em vez disso usamos nomes que representam esses endereços como o nome de função e nomes de variáveis e deixamos o compilador traduzir isso em endereços no vinagre final isso é outro conceito importante nomes de coisas não precisam existir no binário se a gente quiser podemos dizer que o compilador manter os símbolos pra de bugs símbolos são esses nomes os campos nome da de altura não existem no binário Onde estão os valores é só um linguição de bits e só linguagens de mais alto nível
às vezes guardam esses símbolos por padrão são metadados ou dados que explicam os dados e metadados também ocupa um espaço Mas como não são necessários para rodar o programa e sim para divulgar depois não é bom guardar tudo porque seria um desperdício de espaço e você já mexeu com coisas como XML ou Jason eles são grandes e desperdiçam bastante espaço primeiro porque representam tudo como Strings e segundo porque levam os metadados de tudo junto com os dados mas isso é um detalhe que eu vou explorar em outro Episódio aliás é por isso que um Google
inventou coisas com o protobufs se você estiver interessado em mais um assunto para estudar veja protobuf no caso do texto do código nós declaramos símbolos ou nomes para endereços e cadeias de bits para facilitar a vida do programador de Lewis um lugar depois mais a máquina e se não se importa com nada disso para o computador é tudo uma cadeia de bits e só o computador não dá a mínima para como você chama as coisas um significado que dá para ela o código é feito para outros programadores entender em computadores só entendem os binários sem
nome e sem significados só números e endereços entendi esse conceito a parte importante é que tudo tem endereços não só variáveis mas funções também em particular em si podemos pegar a referência de uma função e passar como argumento para outra função da mesma forma como eu passei o endereço da variável Hello para o cliente F imprimir na tela lembra por exemplo vamos ver organizar esse código de criar extract uma função chamada Fiat perns onde passamos como argumento o nome da de altura e um último argumento que é um ponteiro para uma função que não retorna
nada então void mas tem como argumento um strict de pearson dentro dela fase e cozinho antes onde declaramos a história que tiver são preenchemos os campos mas no final executamos a função que vem nesse endereço chamado function Pointer entenda isso a variável function Pointer assim como Aquela Hello dois vai ser só uma referência o endereço para alguma função que tem as características que declaramos que retorna a voz de ou seja nada e tem uma extract parson com o argumento ao colocar um asterisco na frente dela é como se estivéssemos dando cop peixe do nome da
função de verdade aqui executando ela a seguir vamos declarar a função para passar para esse cliente persa vamos chamar de print persson e retorna avoid e esse é limpar som de argumento e dentro é só um print F como fizemos antes mas Norte e diferente de antes onde precisamos declarar acima as funções como usar embaixo estamos declarando o print peço abaixo da função cliente persa porque ela ainda não sabe que essa função que vamos usar ela sós e vai receber uma referência que pode ser para qualquer outra função se a cliente persa chamasse direto a
print persson ela precisaria ter sido declarada antes mas vamos ver a seguir como eu passo a referência dessa função para cliente persa na função Man chamamos Acredite persa um passando os mesmos valores de antes Fábio 43 e 172 e em seguida & eprint persson a quem Estamos pegando a referência o endereço da função e passando com o argumento quando compilamos executamos vemos que a saíram na tela é igual antes esse e Comercial print persa não tá pegando o endereço onde a função tá declarada e passando como argumento para cliente perto é só um interior e
faz cast para uma função cast é ação de declarar que tipo esse número representa para o compilador você saber o que fazer com ela mas só isso não tem graça vamos declarar uma segunda função print parson dois para ver como podemos passar é diferente lá em cima Fazemos uma cópia do verso chamamos de print para São dois e vamos só mudar o jeito que o print F mostra os dados de volta lá embaixo vamos chamar o cliente perto de novo mas passando a referência para esse novo print para São dois depois de compilar e executar
veja que imprimi essa nova versão também a função Create persson aceita qualquer função compatível que tem a mesma assinatura ou seja o tipo de retorno e os tipos de argumentos que ele espera isso é o que chamamos de assinatura de uma função ela só recebe a referência para função que estiver nesse endereço basta essa função tem assinatura correta ou seja aceitar extract de Persa e retornar void ou Nada nisso de uma função você passada como referência para outra função é o que você já deve ter ouvido falar como colbeck é uma função que vai ser
chamada com de volta Beck e qualquer um que tenha se interessado por programação funcional sabe que uma característica importante e funções que recebem outras funções como argumento a função cliente persa é o que em funcionar o povo chamaria de raio reader fanfiction quando em jovens script Python Ruby você usa funções como for each map filtra reduz e outros eles recebem como argumento a referência para outra função normalmente uma função anônima Ou seja que não tem nome e é declarada dentro dos parentes de argumento E com isso você entendeu o primeiro passo para ter uma linguagem
funcional da teoria sim você poderia escrever código sendo jeito funcional mas ninguém faz isso porque não é plástico mas com isso você pode imaginar como você poderia ser usado para criar uma linguagem funcional como o munícipe da vida é assim que a gente começa a manipular uma linguagem para aceitar paradigmas que ela não foi Projetada para fazer e como que aprendemos até agora eu já posso mostrar mais um passo adiante vamos entender o primeiro passo que leva a ser para uma linguagem orientada a objeto com o e lançou objective ser o que eu vou mostrar
a seguir não é a implementação de verdade mas só umas Cunha de como poderia ser onde eu penso orientação objeto só pensa em duas coisas um ponteiro para uma Street e ponteiros para funções cujo primeiro argumento é o que você aprendeu num Pai tô javscript como self ou desse sendo um ponteiro de volta para mesmo instante vamos refatorar a cliente persa no primeiro até agora ela tá declarando a strict na steck quando chama a print persson para duplicando por causa da passagem por valor em vez disso vamos criar e se trate de um hip economizar
espaço no step fazendo passagem por referência Para isso precisamos usar malloc passando o tamanho da estante com um parâmetro e isso para mim é o que significa instanciar um objeto na memória basicamente a locais se passa uma hip para uma estante no caso de ser quando cremos qualquer coisa no chip mas vamos colocar* na frente da variável e essa referência para acessar o valor mais no caso distracting se basta trocar essa notação de ponto para uma certa com tracinho e sinal de maior se você descer para os planos vão PHP já viu essa notação e
eu acho que ela deriva dizem ser mesmo para acessar os campos de uma estante de ser que foi alocada na hip sem precisar os aparentes e pontos basta usar a setinha é a mesma coisa agora vamos tirar o argumento de ponteiro de função do final do cliente persa em vez disso rumo ver para Street de Peterson um novo Campo que é um ponteiro de função chamado Show dentro da crítica perto declaramos que o campo show desse perto aqui está sendo um hip vai apontar para referência da função print perto Porque a gente já tinha finalmente
vamos mudar o tipo de retorno da função para devolver o ponteiro das Street e no final podemos dar retorno e do persa que acabamos de criar e configurar tem já programa orientada a objetos em alguma linguagem pode estar o meio familiar eu chamaria essa função cliente perto de Construtor um construtor é uma função é responsável por alocar espaço para o objeto na memória hip e configurar os valores iniciais desse objeto retornando o endereço uma referência para esse objeto agora vamos usar isso na função Man Primeiro vamos armazenar o ponteiro que Acredite perto não vai criar
uma variável que é um ponteiro um asterisco pearson e passamos os valores que queremos como argumento a esse Construtor e para imprimir esses valores na tela podemos chamar direto um método desse objeto e para quem não sabe método é o nome que damos a funções associadas a um objeto o método show já foi configurado no Construtor para ser um ponteiro para frente peperson a última refatoração que precisamos fazer é mudar a função print perto para usar essa variável selfie para acessar os campos de nome idade e altura se você é de paz não deve estar
começando a se sente e o que métodos de objetos de paz não tem explicitamente o primeiro argumento recebendo o selfie e é o que eu tô simulando aqui em si em Java Script outras linguagens orientadas a objetos em vez de selfie chamamos de diz mas é mais ou menos a mesma coisa só que o primeiro argumento é implícito você não precisa declarar ela mas passa de conta que é linguagem tá botando ela lá para você então só chamando perfume certinha print e passando persson como argumento selfie vai tudo funcionar qual seria o próximo passo para
ficar mais parecido com uma linguagem orientada a objeto para quem não sabe em Se tem uma coisa chamada para processamento que é reescrever o código antes de compilar se você é de Java script pensa e como transpiler por exemplo lá no topo do arquivo podemos declarar uma #definir e dizer que toda vez que achar escrito Class pode trocar para extract antes de compilar Onde está Street version podemos substituir como classe e vamos lá usar a função de procurar e substituído editor e bumbum olha só com o de frente parece que estão lidando com uma linguagem
orientada a objetos de verdade e se você aguentou até aqui espero que tenha conseguido minimamente visualizar o que são os diferentes tipos de dados as diferenças entre inteiros e Flores arrezzi tampa Os Estranhos como dados são alocados na steck que a pilha e como a execução de um programa com funções que chamam outras funções vai sendo empilhado e desempilhados da steck Como tudo tem endereços ou referências incluindo funções algumas linguagens expõe referências a funções mas não permitem manipular essas referências para apontar para outras regiões de memória JavaScript assim um usava lá atrás só tinha referência
a um objeto por isso a única forma de passar funções para outras funções era primeiro encapsulado uma classe anônima Instância e passar a referência do objeto com o argumento para outras funções em baixo dos panos é assim que as coisas funcionam para complementar recomendo rever os vídeos sobre gerenciamento de memória quando fazemos programinha simples que alocam poucos dados e não tem uma recursão maluca Ô Ester que é mais que suficiente você não precisa lidar com o chip o problema já louca coisas um hip é que quando terminar a função faz a locação o ponteiro sidetech
Mas o que foi alocado no hip continua lá ocupando espaço se você não deve fluir para liberar explicitamente memória na Ri Happy não se desempilhe a sozinha com isso surge a necessidade de um garbage collector ou outros truques como o ar que diz Swift para limpar o chip só que garbage collector não faz milagres Ele sempre vai reservar mais memória do que realmente precisa e sempre vai causar pausas na execução do programa para fazer essa limpeza de tempos em tempos mesmo se você tiver memória sobrando para desperdiçar essas pausas para limpeza sempre vão ser um
problema e é o Que linguagens com suíte honra bom então evitar por isso são melhores para fazer coisas como sistemas operacionais driver ou coisa de mais baixo nível que vão ser eficientes no uso de recursos evita pausas de manutenção o máximo possível o mesmo não se pode dizer de jabá fechar pegou linguagens interpretadas Como já me script Python loop PHP são extensões bem pesadas em cima de ser elas adicionam diversas funcionalidades para facilitar a programação mais por baixo dos panos o que faz as funcionárias mais rápido em mais eficiente são bibliotecas escrita sem ser uma
biblioteca escritas olhem Python ou java script nunca vai ser nem tão rápida nem tão eficiente por isso funções com o tempo tô grafia funções de aiocá lidar com arquivos o pacote de rede funções Matemáticas e tudo mais é escrito em ser eu chamo essas linguagens de linguagem escola você só escreve a cola em pai não quer mais sentar com mais simples para mexer com funções mais complicadas que estão escritas em seus e por exemplo em machine learning Python não é importante porque as funções de um tensor flor são todas escritas em C plus plus Se
você usar os ai pai para computação científica de novo as funções são todas em se pôs o fortão nenhuma linguagem Cola é rápido o suficiente para essas coisas são boas como cola para consumir essas coisas mais fácil Se você mexe em machine learning Python você é só um consumidor de ferramentas escritas em si los ou cê e faz cola em Python tem nenhum problema nisso e na prática a maioria de vocês assistindo nunca vai precisar de mais que isso linguagem esqueçam cola nunca vão ser boas para fazer o que eu chamo de sistemas coisas com
drivers criptografia processamento uma segunda de dados como um banco de dados ou mesmo Protocolos de rede eficientes ela sempre vão ser só a cola para sistemas feitos em cepos ou se por isso eu recomendo que você saiba no mínimo uma linguagem de mais baixo nível como o host e junto uma linguagem cola para ter produtividade como java script em Python Quem só sabe linguagem escola sempre vai achar que o que acontece no baixo nível É Mágica e com o Episódio de hoje eu espero ter conseguido quebrar um pouco dessa mágica e fazer vocês enxergar em
suas linguagens favoritas com outros olhos Claro tudo que eu falei rápido em um episódio é o que se ensina em um mini um semestre em Ciências da Computação Talvez um ano ou até mais eu só mencionei estruturas de dados simples não falei de listas ligadas à árvores redblack e Viel e nem cheguei a falar dos algoritmos para lidar com essas estruturas Quem sabe em outro Episódio no futuro mas entenda tudo que eu falei hoje é o básico em Ciências da Computação se você se considera programador e nunca viu nada do que eu expliquei hoje considere
estudar e treinar mais isso vai te ajudar a subir para o próximo nível na programação se ficaram com dúvidas mandem nos comentários abaixo inclusive se e tudo que eu disse aqui ajudem a responder as dúvidas dos colegas nos comentários também não deixe de assinar o canal e clicar no Sininho para não perder os próximos episódios Compartilhe o video para ajudar o canal a gente se vê até mais
Copyright © 2024. Made with ♥ in London by YTScribe.com