[Música tocando] DAVID J. MALAN: Tudo bem. [Risos] Bem-vindo de volta. Isto é CS50. E este final de semana cinco. E até agora, temos praticamente tomado como certo que há existe este compilador Clang, que você tem foi invocar por meio deste outra ferramenta chamada Verifique que de alguma forma magicamente transforma seu código-fonte em código objeto, os zeros e uns que o seu CPU de computadores, centrais unidade de processamento, realmente entende. Mas acontece que há um número que é acontecendo debaixo do capô em entre a entrada ea saída. E eu gostaria de propor que a carne que em um pouco mais de detalhes em estas quatro etapas, tem uma coisa chamada pré-tratamento, algo chamado de compilação, o que vimos, algo chamado montagem e algo chamado de ligação. Então, até agora, em alguns dos nossos programas, tivemos afiada inclui. Mais recentemente tivemos alguns sharp define para constantes. Assim, verifica-se que as coisas que são prefixados com o símbolo de hash ou o símbolo de libra são pré-processador directivas. Isso é apenas uma maneira elegante de dizer que é uma linha de código que é realmente convertido em outra coisa antes do computador até tentar converter seu programa em zeros e uns. Por exemplo, afiado inclui padrão I / O. H, praticamente significa apenas ir à frente, pegue o conteúdo dos arquivos STDIO.H e colá-los ali mesmo. Portanto, não zeros e uns nesse ponto ainda. É realmente apenas uma substituição. E isso é feito durante a chamada fase de pré-processamento, quando você realmente executado Clang ou especificamente Fazer na maioria dos casos. Então, tudo isso que vem acontecendo primeiro automaticamente até o momento. Em seguida, vem a etapa de compilação. Mas temos sido simplificada compilação. Compilando um programa realmente significa levá-lo de algo como C, o o código-fonte que tenho escrito, para baixo a algo chamado montagem. Linguagem assembly é um nível inferior linguagem que, felizmente, não vamos têm muita oportunidade de escrever este semestre. Mas é no nível mais baixo da sensação de que você, literalmente, começar a escrever somar e subtrair e multiplicar e carregar da memória e guardar a memória, o instruções muito básicas que um computador, debaixo do capô, realmente entende. Por último, a montagem leva essa língua para os zeros e uns que temos sido descrevendo assim longe. E, na verdade, por último, há o chamado ligando fase, que vamos ver em apenas um momento, que combina os zeros e uns com zeros e as outras pessoas antes que você criou. Por isso, considero este programa super simples. Foi da Semana 1. Ele apenas disse: Olá Mundo, no ecrã. Nós rodamos este através Clang. Ou corremos através Fazer que decorreu Clang. E transmitido no momento em que alguns zeros e uns. Mas acontece que há um passo intermediário. Se eu passar por aqui - oops, não quero vê-lo ainda. Se eu passar por aqui para o meu aparelho e eu abrir hello.c, aqui é o mesmo programa. E o que eu vou fazer no meu terminal janela é aqui que eu vou executar Clang ao invés de fazer, que automatiza todos os quatro esses passos para nós. E eu vou fazer clang-S e então hello.c e depois entrar. E eu fico um prompt piscando novamente, o que é bom. E agora em uma janela um pouco maior, Vou abrir gedit aqui. E eu vou abrir um arquivo que, Acontece, é chamado hello.s esta que contém linguagem assembly Me referi anteriormente. E isso é o que é chamado de montagem linguagem, nível bastante baixo instruções que seu processador Intel ou seja o que for que está dentro entende. Mov e é para o movimento. chamada é para chamando uma função de nível muito baixo. sub é para subtrair. Então, quando você tem um determinado CPU dentro do seu computador, o que o torna distintas, contra outro CPUs no mercado, é que as instruções que entende e muitas vezes o quão eficiente ele é, o quão rápido é a execução de alguns dessas instruções. Agora, para saber mais sobre isso, você pode ter próximo CS61 queda na faculdade. Mas aqui temos, por exemplo, alguns identificadores que pode parecer familiar. ola.c é o nome do programa. . Texto - não há muito interesse lá agora, lembre-se que o texto segmento, de segunda-feira, é quando em memória de seu programa realmente acaba. Então é isso, pelo menos vagamente familiarizados lá. Aqui, é claro, é uma menção da nossa função principal. Rolagem para baixo, estes referem-se a coisas chamados registros, muito pequenos pedaços de memória dentro de sua CPU atual. E se rolar mesmo Além disso, eu vejo algum tipo menção indireta de ASCII. E há, de fato, é que a string, Olá, vírgula mundo. Assim, longa história curta, esta tem sido acontecendo para você, automaticamente, debaixo da capa de todo este tempo. E o que está acontecendo realmente é uma vez você correr Clang, ou por meio de Faça, você está ficando em primeiro lugar, a partir do código fonte, o assim chamado em linguagem assembly. Então Clang é converter esta assembléia linguagem de baixo para zeros e uns. E este é o slide que começamos nossa discussão na Semana 0 em - e, em seguida, em uma semana. E então, finalmente, aqueles zeros e uns são combinados com os zeros e uns a partir dessas bibliotecas que temos vindo a tomar para concedido como Padrão I / O ou a Biblioteca de corda ou mesmo a biblioteca de CS50. Então, para pintar o quadro mais visualmente, temos hello.c. E, é claro, usa o printf funcionar a dizer, Olá mundo. A etapa de compilação leva-lo até o arquivo que acabamos de ver hello.s, mesmo Apesar de que é normalmente suprimido automaticamente para você. Mas esse é o código de montagem no passo de meio. E então, quando nós montamos a montagem linguagem, por assim dizer, que é quando você obter os zeros e uns. Então, nós temos ampliado de forma eficaz hoje em o que temos vindo a tomar para concedido, significa passar o código-fonte do código-objeto. Mas, finalmente, agora que mesmo quadro - vamos empurrá-la para o lado esquerdo. E note que no topo há Mencionei stdio.h. Isso é um arquivo que nós incluímos em quase todos os programas que você escreveu. E esse é o arquivo cujo conteúdo Obter cópia colado, eficazmente sobre seu código. Mas verifica-se que, em um computador sistema em algum lugar, há provavelmente um arquivo stdio.c que alguém escreveu anos há que implementa todas as funções que foram declaradas em stdio.h. Agora, na realidade não é, provavelmente, em seu Mac ou PC ou até mesmo no CS50 aparelho é um código C cru. Alguém já compilou e incluiu . O arquivo de código-objeto ou. Uma arquivo, que refere-se a uma biblioteca compartilhada que foi pré-instalado e pré-compilados para você. Mas suponha que há de fato existe no nosso stdio.c computador em paralelo com Clang. Seu código está sendo compilado e montado. código stdio.c 's está sendo compilado e montado, de modo que este último passo, aqui, temos que de alguma forma link, por assim dizer, os seus zeros e uns com seus zeros e uns em uma programa simples que, finalmente, é Olá chamado apenas. Então essa é toda a magia que é vem acontecendo até agora. E vai continuar a tomar estes processos de concessão, mas perceber há um monte de detalhes suculentos acontecendo debaixo lá. E é isso que faz com que seu computador com Intel inside particularmente distinta. Então, com essa nota, se você gostaria de se juntar a nós para o almoço desta sexta-feira, fazer ir para o local cs50.net/rsvp habitual, 13:15 desta sexta-feira. E agora alguns anúncios. Portanto, temos uma boa notícia. E nós temos uma má notícia. Comece com uma boa notícia aqui. [Gemendo] Tudo bem. Bem, é tecnicamente um feriado, assim não é tanto um presente de nós. Mas, então, a má notícia é claro. [Gemendo] Passei um monte de tempo nestas animações. [Risos] Haverá uma sessão de avaliação esta próxima segunda-feira. Vai estar em 5:30 PM. Nós vos fará lembrar de todos esses detalhes via e-mail sobre o curso de site em apenas um par de dias. Ele será filmado e disponibilizado pouco depois. Então, se você não pode fazer que segunda-feira slot de noite, não se preocupe. Seções na próxima semana também vai concentrar-se em revisão para o teste. Se a sua seção é na segunda-feira, que é de fato férias da universidade, vamos ainda reunir-se em seção. Se você simplesmente não pode fazer isso seção, porque você vai de distância, isso é bom. Participar de uma seção de terça-feira ou domingo ou tune-se para a seção de Jason, que é disponível online. Assim, mais uma má notícia. Assim, de acordo com o plano de estudos, temos palestra na próxima sexta-feira. Mas a boa notícia - claramente, eu passei muito tempo com isso. [Risos] Vamos cancelar próxima palestras de sexta-feira. Assim que será um presente para nós, de modo que você pode realmente ter um bom descanso em entre esta semana e duas semanas daí. Portanto, não palestras na próxima semana, apenas uma pequena pouco quiz, para o qual deve ser ficando cada vez mais animado. Então, vamos agora voltar nossa atenção para algo que é realmente mais visual e mais emocionante e para definir o estágio para o que vai estar no horizonte em apenas um par de semanas. Após o primeiro teste, vamos transformar o foco da nossa conjuntos de problemas para outro problema específico do domínio, que de forense ou de segurança em geral. Na verdade, o tractor com este problema conjunto é para mim um dos ensinando companheiro ou CAs para atravessar campus tirar algumas fotografias identificáveis, mas não as pessoas óbvias, lugares ou coisas, então todo ano eu de alguma forma conseguem apagar acidentalmente ou danificar o cartão de mídia digital que está dentro da nossa câmera. Mas não é grande coisa. I pode ir em frente e ligue que no meu computador. Eu posso fazer uma imagem forense do mesmo, assim para falar, copiando os zeros e aqueles fora do que o cartão de memória, seja é um cartão SD ou cartão de memória flash compacto ou o que você está familiarizado. E então podemos entregar isso. E assim o desafio à frente, entre outros coisas para você, será para escrever Código C, que se recupera de um monte de JPEGs para mim e revelou será essas pessoas, lugares ou coisas. E também vou falar, neste problema definir e nos dias que virão, sobre gráficos em geral. Nós usamos eles, um curso, para sair. Mas você espécie de dado adquirido existe estas noções de alto nível de retângulos e ovais. Mas debaixo do capô existem pixels. E você tinha que começar pensando sobre isso. Ou você vai para a p-set 4 tem que pensar sobre a diferença entre os tijolos, como rapidamente você está bola está se movendo através de a tela para sair. Portanto, não há essa noção de pontos em sua tela que é entram em jogo já. Agora o que se vê, porém, é o que você chegar em uma tela de computador. Se você já assistiu a algum bem ou TV ruim, as chances são eles praticamente tratar o público como technophobes que realmente não sei muito sobre informática. E por isso é muito fácil para a polícia detetive para dizer, não é limpar isso para mim? Ou melhorar, certo? Melhorar é como a palavra da moda em mais qualquer programa relacionado crime. E a realidade é que se você demorar muito imagem borrada de um suspeito de fazer algo ruim, você não pode apenas melhorá-lo. Você não pode ampliar infinitamente. Você não pode ver o brilho de alguém da olho que cometeu que determinado crime, apesar da prevalência desta na TV. E assim, com que vamos motivar que próximo conjunto de problemas com um vislumbre alguns shows com o qual você pode estar familiarizado. [REPRODUÇÃO] -OK. Agora, vamos dar uma boa olhada em você. -Espere. Correr de volta. -Espere um minuto. Vá para a direita. -Não. Congelar isso. Ecrã completo. -OK. Congelar isso. Aperte-se sobre isso, sim? -Vector na nessa cara pela roda traseira. -Zoom em direito aqui neste local. -Com o equipamento certo, a fotografada pode ser ampliada e afiadas. -O que é isso? -É um programa de melhoramento. -Você pode esclarecer isso qualquer? -Eu não sei. Vamos melhorá-lo. Seção A-6-Enhance. -Eu aumentei os detalhes e - -Eu acho que é o suficiente para melhorar. Liberá-lo para minha tela. -Melhorar a reflexão em seus olhos. -Vamos fazer isso através de aprimoramento de vídeo. -Edgar, você pode melhorar isso? -Segurem-se. -Tenho vindo a trabalhar sobre esta reflexão. -Alguém reflexão de. -Reflexão. -Há uma reflexão do rosto do homem. -A reflexão. -Há uma reflexão. -Dê um zoom no espelho. -Você pode ver uma reflexão. -Você pode melhorar a imagem a partir daqui? -Pode aumentar ele aqui? -Você pode melhorá-lo? -Você pode melhorá-lo? -Podemos melhorar isso? -Você pode melhorá-lo? -Espere um segundo, eu vou melhorar. -Zoom na porta. -X10. -Zoom. [Risos] -Mover-se dentro -Espere, pare. -Parar. -Pausa-lo. Girar em torno de 75 graus por favor, o vertical. [Risos] -Pare, e de volta para a parte sobre a porta novamente. -Tem um intensificador de imagem que pode bitmap? -Talvez possamos usar o Pradeep Sen método para ver nas janelas. -Este software é o estado da arte. -O valor ícone está desligado. -Com a combinação certa de algoritmos. -Ele levou algoritmos de iluminação para o próximo nível e posso usá-los para melhorar esta fotografia. -Lock e ampliar o eixo z. -Melhorar. -Melhorar. -Melhorar. Congelamento e melhorar. [FIM REPRODUÇÃO DE VÍDEO] DAVID J. MALAN: Então Set Problem 5 é o que está por vir lá. Então, vamos em breve ter uma melhor compreensão de quando e por que você pode ea nossa não pode melhorar nesse sentido. Mas, primeiro, vamos voltar nossa atenção para alguns dos blocos de construção vamos precisa ser capaz de contar essa história. Então, lembro que tirei esta imagem em Segunda-feira e um pouco na semana passada. E isso descreve o layout das coisas na memória do seu computador quando execução de algum programa. O segmento de tecnologia em cima, aviso, refere-se para os zeros e uns reais que compõem o seu programa. Há, abaixo, alguns inicializado ou dados não inicializados, que tipicamente refere-se a coisas como constantes ou strings ou variáveis ​​globais que têm previamente declarado. Há a pilha, mas nós vamos chegar de volta para que daqui a pouco. E depois há a pilha. Muito parecido com uma pilha de bandejas no cafeteria, este é o lugar onde a memória fica em camadas e camadas sempre você faz o que em um programa? Qual é o uso de pilha para? Sim? Chamada de função. Toda vez que você chamar uma função, é dado ao pedaço de memória para o seu variáveis ​​locais ou seus parâmetros. E pictoricamente, vemos que a cada Função chamada sucessiva, quando A chamadas B chama C chamadas D, eles se em camadas na pilha. E dentro de cada uma das referidas fatias de memória é essencialmente uma extensão única para essa função, o que, evidentemente, é problemático se você quiser entregar a partir de uma função para outra Um pedaço de dados que você quer que ele para mutar ou alterar. Então, qual foi a nossa solução de possibilitar Uma função representada por uma pilha quadro para alterar a memória dentro de outro quadro de pilha? Como os dois falam um para o outro? Assim, por meio de ponteiros ou endereços, que, novamente, apenas descrever o local onde em memória, por meio de um específico número mordida, o particular valor pode ser encontrado. Então lembro da última vez também continuamos a história e olhou para a bastante programa de buggy. E este programa é buggy para poucos razões, mas o mais preocupante é porque ele não consegue verificar o que? Sim, ele não consegue verificar a entrada. Desculpe? Se for mais de 12 caracteres. Então, muito esperta, ao chamar memcopy, que, como o nome sugere, apenas memória cópias de seu segundo argumento em seu primeiro argumento. O terceiro argumento, muito esperta, é verificado para se certificar de que você não copiar mais do que, no presente caso, o comprimento de bar, número de caracteres, para o destino, o que é isto série C. Mas o problema é que o que se a própria C não é grande o suficiente para lidar com isso? Você vai copiar o número de bytes que você já foi dado. Mas o que você realmente tem mais bytes que você tem espaço para? Bem, este programa muito tolamente apenas cegamente passa a ter tudo o que é dado, Olá barra invertida é 0 ótimo se string é curto suficiente, como cinco caracteres. Mas se é realmente 12 caracteres ou 1200 caracteres, vimos da última vez que você está indo só para completamente sobrescrever a memória que não pertence a você. E o pior caso, se você substituir esse parte vermelha lá que chamamos de endereço do remetente - isso é apenas onde o computador automaticamente, para você, por trás da cenas, dobras de distância um valor de 32 bits que lembra-lo para o endereço que deveria voltar quando foo, esta outra função, é feito de execução. É uma migalha de pão de tipo ao qual ela retorna. Se você substituir o que, potencialmente, se você é o cara mau, pode poderia potencialmente assumir computador de alguém. E você vai certamente lançá-lo na maioria dos casos. Agora, este problema só foi agravado como começamos a conversar sobre a memória gestão em geral. E malloc, para alocação de memória, é uma função que podemos usar para alocar memória quando não sabemos com antecedência que pode precisar de algum. Assim, por exemplo, se eu voltar para o aparelho aqui. E eu abrir a partir do último hello2.c tempo, recordar este programa, que parecia um pouco algo como isto, apenas três linhas - indicar o seu nome, o nome string, no lado esquerdo, é igual a getstring. E, então, imprimi-lo, o nome do utilizador. Portanto, este era um super programa simples. Para ser claro, deixe-me ir em frente e torná-Olá-2. Eu vou fazer o ponto barra Olá-2. Diga seu nome - David. Enter. Olá David. Parece que funciona OK. Mas o que realmente está acontecendo sob capô aqui? Primeiro vamos descascar algumas camadas. String é apenas um sinônimo temos percebi para quê? Estrela Char. Então, vamos torná-lo um pouco mais misterioso mas tecnicamente mais correto que este é uma estrela char, o que significa que nome, sim, é uma variável. Mas o que armazena o nome é o endereço de um char, que se sente um pouco estranho porque eu estou recebendo de volta uma string. Eu estou voltando múltipla caracteres não um char. Mas, claro, você só precisa do primeiro endereço do char para lembrar de onde o corda toda é porque porquê? Como você descobrir onde está o fim do a string é saber o começo? A barra invertida zero. Assim, com essas duas pistas que você descobrir antes do começo e do fim da qualquer seqüência são, contanto que eles são formada adequadamente com que null terminador, que invertida zero. Mas isso está chamando getstring. E verifica-se que getstring todo esse tempo tem sido uma espécie de batota para nós. Ele vem fazendo este trabalho, com certeza, recebendo uma string do usuário. Mas onde é que a memória vindo de? Se voltarmos para a imagem aqui e aplicar a definição de apenas um há pouco, que a pilha é onde memória acontece quando as funções são chamadas, por essa lógica, quando você chama getstring, e então eu digitar D-V-A-I-D Enter, em que é D-A-V-I-D barra invertida a zero armazenado, com base no história que nos disse até agora? Parece estar em a pilha, certo? Quando você liga para obter corda você tem um pequeno pedaço de memória na pilha. Então, é lógico que a D-A-V-I-D invertida zero é armazenado existe na pilha. Mas espere um minuto, getString retornos essa seqüência, por assim dizer, o que significa é bandeja da cafeteria é retirado da pilha. E disse da última vez que tão logo a função retorna, e você ter que tabuleiro, por assim dizer, fora da pilha, o que você pode assumir sobre os restos de que a memória? Eu meio que redesenhou-os como pontos de interrogação porque efetivamente se tornar valores desconhecidos. Eles podem ser reutilizados quando alguns próxima função é chamada. Em outras palavras, se acontecer a armazenagem - Eu vou tirar uma foto rápida aqui da pilha. Se acontecer de estar chegando ao fundo do meu segmento de memória, e vamos dizer que este é o local de memória ocupado pelo principal e talvez arg c e arg v e qualquer outra coisa no programa, getstring quando é chamado, presumivelmente getstring fica um bloco de memória aqui. E então D-A-V-I-D alguma forma termina nesta função. E eu vou simplificar. Mas vamos supor que o seu D-A-V-I-D barra invertida zero. Então isso muitos bytes são usados ​​em o quadro para getstring. Mas, tão logo retorna getString, nós disse da última vez que essa memória sobre aqui tudo se torna - woops! - tudo se torna efetivamente apagados. E podemos pensar nisso agora como questão marcas porque quem sabe o que vai tornar-se de que a memória. Na verdade, eu muitas vezes chamar funções excepto getstring. E assim que eu chamo algum outro função de getstring, talvez não em este programa específico que apenas olhou mas em alguns outros, certamente alguma outra função pode acabar sendo dado este ponto seguinte na pilha. Portanto, não pode ser que as lojas getString D-A-V-I-D na pilha, porque eu faria imediatamente perder acesso a ela. Mas nós sabemos que eles getString só retorna o que? Ele não está voltando para me seis caracteres. O que é que realmente se voltando conclui-se da última vez? O endereço do primeiro. Então, de alguma forma, quando você chamou getstring, é alocar um bloco de memória para a corda que o tipo e os usuários endereço, em seguida, retornar dela. E verifica-se que quando você quer funcionar para alocar memória neste caminho e voltar para a pessoa que ligou essa função, o endereço que pedaço de memória, é absolutamente não pode colocá-lo na pilha no baixo, porque funcionalmente é apenas vai se tornar o seu muito rapidamente, assim que você pode provavelmente adivinhar onde estamos indo provavelmente para lançá-lo em vez disso, a chamada pilha. Então, entre o fundo da sua memória de layout e do alto de sua memória do disposição são um monte de segmentos. Uma delas é a pilha, e à direita acima, é o heap. E pilha é apenas um pedaço diferente de memória que não é usado para funções quando eles são chamados. É usado para a memória de longo prazo, quando você quer uma função para pegar alguns memória e ser capaz de segurá-la sem perder o controle sobre ele. Agora você poderia talvez imediatamente ver que esta não é necessariamente um design perfeito. Tal como o seu programa de memória alocada em a pilha, ou como vocês chamam mais e mais funções, ou como você alocar memória na pilha com malloc fora como getstring está fazendo, o que claramente parece ser problema inevitável? Certo. Como o fato de que essas setas estão apontando um para o outro não augura nada de bom. E, de fato, nós poderíamos bater muito rapidamente um programa em qualquer número de maneiras. Na verdade, eu acho que pode ter acidentalmente uma vez feito isso. Ou se não, vamos fazê-lo deliberadamente agora. Deixe-me ir em frente e escrever super-rápida um programa chamado dontdothis.c. E agora eu vou entrar aqui e não afiada incluir stdio.h. Vamos declarar a função foo leva Sem argumentos, o que é denotado como bem por nula. E a única coisa foo vai fazer é chamada foo, o que provavelmente não é o mais inteligente idéia, mas que assim seja. Ent void main. Agora a única coisa principal que vai a fazer é chamar foo bem. E, apenas por diversão, eu vou à frente e dizer printf "Olá a partir de foo ". OK. Então, se eu não cometer erros, Faça dontdothis dot barra. E vamos fazê-lo em uma janela maior - dot slash, dontdothis. Vamos. Uh oh. Aparentemente, você pode fazer isso. Droga. OK. Espere. Stand by. Será que nós - Fizemos usá-lo com Make. [Suspira] Eu sei, mas eu acho que nós acabei de excluir isso. Uh, sim. Droga. Resolva este Rob. O quê? É muito simples. Sim, voltamos a otimização off. OK, stand bye. Agora sinto-me melhor. OK. Tudo bem. Então, vamos recompilar isso - Faça você dontdothis. Você pode ter que mudar o nome deste para dothis.c em apenas um momento. Lá vamos nós. Obrigado. OK. Assim, o fato de que eu estava imprimindo algo foi realmente apenas retardando o processo pelo qual nós teria chegado a esse ponto. OK. Ufa! Então, o que está realmente acontecendo? A razão lá, assim como um aparte, é fazer qualquer coisa em termos de entrada e produção tende a ser mais lento, porque você tem que escrever caracteres para o tela, tem que rolar. Assim, longa história curta, eu tinha realmente Aconteceu tão impaciente, teríamos vi esse resultado final também. Agora que eu tenho passeio dos print-ups, vemo-lo imediatamente. Então, por que isso está acontecendo. Pois bem, a explicação simples, é claro, foo é que provavelmente não deveria ser que se autodenomina. Agora, em termos gerais, esta é a recursividade. E nós pensamos que algumas semanas atrás recursiva é bom. Recursividade é dessa forma mágica de expressar-se de super sucinta. E ele simplesmente funciona. Mas há uma característica fundamental de todos os programas recursivos com quem falamos cerca e olhou para, até agora, o que era que eles tinham o quê? Um caso base, que era um pouco difícil coded caso o referido em algumas situações não chamar foo, o que é claramente não é o caso aqui. Então, o que está realmente acontecendo em termos de esta imagem? Bem, quando principal chama foo, que recebe uma fatia de memória. Quando chama foo foo, ele fica uma fatia de memória. Quando chama foo foo, ele recebe uma fatia. Ela recebe uma fatia. Ela recebe uma fatia. Porque foo nunca está voltando. Nós nunca está apagando um daqueles quadros da pilha. Então, nós estamos soprando através da pilha, não de mencionar quem sabe o que mais, e estamos ultrapassando os limites do nosso o chamado segmento de memória. Erro ir segmentação falsa. Portanto, a solução há claramente, não faça isso. Mas a maior implicação é que, sim, não é absolutamente um limite, mesmo se ele não está bem definido, a forma como muitas funções que você pode chamar de uma programa, quantas vezes uma função pode chamar a si mesma. Assim, mesmo que fizemos pregar recursão como essa coisa mágica potencialmente um par de semanas atrás para o sigma função, e quando tivermos os dados estruturas e CS50, você verá outro aplicações para ele, não é necessariamente a melhor coisa. Porque se uma função chama a si mesmo, chama-se, mesmo se não houver uma base caso, se você não acertar que caso base para 1.000 chamadas ou 10.000 chamadas, por que o tempo que você pode ter executado fora da sala em seu chamado pilha e sucesso alguns outros segmentos de memória. Por isso, também é um projeto de trade-off entre elegância e entre robustez de seu especial implementação. Portanto, não há outra desvantagem ou Outra pegadinha com o que temos vindo a fazer até agora. Quando liguei getstring - deixe-me voltar em Olá-2. Repare que eu estou chamando getstring, que está retornando um endereço. E afirmamos hoje que o endereço é a partir do heap. E agora eu estou imprimindo a cadeia nesse endereço. Mas nós nunca chamou a oposto getstring. Nós nunca tivemos a calll uma função como ungetstring, onde a mão de volta essa memória. Mas, francamente, nós provavelmente deveria ter sido. Porque se continuar perguntando o computador para a memória, por meio de alguém como getstring mas nunca devolvê-lo, com certeza isso também é obrigado a levar a problemas em que corremos de memória. E, de fato, podemos olhar para estes problemas com a nova ferramenta, cujo uso é um pouco enigmática para digitar. Mas deixe-me ir em frente e molhe-se na tela em apenas um momento. Eu estou indo para ir em frente e correr Valgrind com parâmetro cujo primeiro comando argumento de linha é o nome desse programa Olá-2. E, infelizmente, é saída é atrozmente complexo sem uma boa razão. Assim, vemos toda essa confusão. David é expor meu nome. Então esse é o programa realmente funcionando. E agora temos essa saída. Então Valgrind é semelhante em espírito de GDB. Não é um depurador per se. Mas é um verificador de memória. É um programa que vai executar o seu programar e dizer-lhe se você perguntasse a um computador para a memória e nunca entregou para trás, ou seja, assim que você tem um vazamento de memória. E vazamentos de memória tendem a ser ruim. E você é que os usuários de computadores têm provavelmente sentiu isso, se você tem um Mac ou um PC. Alguma vez você já usou o computador para tempo e não reiniciado em vários dias, ou você só tem um monte de programas em execução, ea coisa maldita desacelera para uma parada, ou pelo menos é super chato de usar, porque tudo ficou super lento. Agora que pode ser qualquer número de razões. Poderia ser um loop infinito, um bug no código de alguém, ou, mais simplesmente, pode significar que você está usando mais memória, ou tentar, do que o seu computador realmente tem. E talvez há um bug em algum programa que continuo a perguntar para a memória. Browsers há anos eram notórios por este, pedindo mais e mais memória mas nunca entregá-lo de volta. Certamente, se você tiver apenas um finito quantidade de memória, você não pode pedir infinitamente muitas vezes para alguma dessa memória. E assim, o que você vê aqui, embora novamente a saída do Valgrind é desnecessariamente complexo para olhar em primeiro lugar, esta é a parte interessante. Heap - em uso na saída. Então aqui é o quanto de memória foi em uso na pilha no tempo meu programa saiu - aparentemente, seis bytes em um bloco. Então eu vou para acenar as mãos em que um bloco é. Pense que é apenas um pedaço, um mais palavra técnica para pedaço. Mas, seis bytes - quais são os seis bytes que ainda estavam em uso? Exatamente. D-A-V-I-D barra invertida zero, cinco letras nome mais o terminador nulo. Portanto, este programa Valgrind notado que eu perguntou por seis bytes, aparentemente, por forma de getstring, mas nunca deu-lhes de volta. E, na verdade, isso não pode ser assim óbvio, se o meu programa não é três linhas, mas é 300 linhas. Assim, podemos realmente dar outro comando argumento de linha de Valgrind para torná-lo mais detalhado. É um pouco chato para se lembrar. Mas se eu fizer - vamos ver. Vazamento - Foi ele vazar - mesmo que eu não me lembro o que é fora de mão. - Vazamento de verificação é igual a integral. Sim, obrigado. - Vazamento de verificação é igual a integral. Enter. Mesmo programa está sendo executado. Digite David novamente. Agora eu vejo um pouco mais detalhadamente. Mas abaixo o resumo do heap, que é idêntica à de quatro - ah, isso é bem legal. Agora Valgrind está realmente procurando um pouco mais no meu código. E ele está dizendo que, aparentemente, malloc em linha - que diminuir o zoom. Na linha - não vemos que linha é. Mas malloc é o primeiro culpado. Há um blog em malloc. Tudo bem? OK, não. Certo? Liguei getString. getstring aparentemente chama malloc. Então, qual linha de código é, aparentemente, a culpa por ter alocados essa memória? Vamos supor que quem escreveu malloc tem sido em torno de tempo suficiente para que seja não é culpa deles. Por isso, é provavelmente a minha. getString em cs50.c - o que é uma arquivo em algum lugar no computador - na linha 286 parece ser o culpado. Agora vamos supor que CS50 tem sido em torno de quantidade razoável de tempo, então nós também somos infalíveis. E por isso não é, provavelmente, em getString que o erro se encontra, mas sim em Olá linha-2.c 18. Então, vamos dar uma olhada o que que a linha 18 era. Oh. De alguma forma, esta linha não é necessariamente carrinho, por si só, mas é a razão por trás desse vazamento de memória. Tão super simples, o que faria intuitivamente ser a solução aqui? Se nós estamos pedindo para a memória, nunca foram dando-lhe de volta, o que parece ser um problema, porque ao longo do tempo o meu computador pode ficar sem memória, pode diminuir para baixo, coisas ruins podem acontecer, bem, qual é a solução simples e intuitiva? Basta dar-lhe de volta. Como você liberar essa memória? Bem, felizmente, é muito simples apenas para dizer o nome livre. E nós nunca fiz isso antes. Mas você pode pensar essencialmente de livre como o oposto do malloc. livre é o oposto do alocação de memória. Então, agora deixe-me recompilar isso. Faça Olá-2. Deixe-me executá-lo novamente. Olá-2 David. Assim, parece que trabalhar em exatamente da mesma maneira. Mas se eu voltar para Valgrind e re-executar esse mesmo comando no meu recém- compilado programa, digitando em meu nome como antes - Nice. Resumo Heap - em uso na saída - zero bytes, em blocos zero. E isso é super legal, todos blocos de pilha foram libertados. Sem vazamentos são possíveis. Então, chegando-se, não com Problema Set 4, mas com Problem Set 5, as forense e para a frente, isso também vai se tornar um medida da justeza de sua programa, se você tem ou não ou não tem vazamentos de memória. Mas, felizmente, não só você pode raciocinar através deles, intuitivamente, que é, sem dúvida, mais fácil para pequenos programas mas mais difícil para programas maiores, Valgrind, para esses programas maiores, pode ajudar a identificar o problema particular. Mas há um outro problema que possa surgir. Deixe-me abrir este arquivo aqui, que é, mais uma vez, um exemplo um tanto simples. Mas vamos nos concentrar no que este programa faz. Isto é chamado memory.c. Vamos postar mais tarde hoje no zip do código-fonte de hoje. E notem que eu tenho uma função chamada f que não recebe argumentos e retorna nada. Na linha 20, eu estou aparentemente declarar uma ponteiro para um int e chamando-x. Estou atribuindo é o retorno valor de malloc. E só para ficar claro, quantos bytes sou Eu provavelmente voltando de malloc nesta situação? Provavelmente 40. Onde você tirou isso? Bem, se você se lembra que um int é muitas vezes 4 bytes, pelo menos é na aparelho, 10 vezes 4 é, obviamente, 40. Então malloc está retornando um endereço de um bloco de memória e armazenamento que resolver em última instância, x. Então, para ser claro, o que então está acontecendo? Bem, deixe-me voltar a nossa imagem aqui. Deixe-me não apenas tirar do fundo do meu memória do computador, deixe-me ir em frente e tirar todo o retângulo que representa toda a minha RAM. Vamos dizer que a pilha É na parte inferior. E há um segmento de texto em os dados não inicializados. Mas eu só vou abstracto, aquelas outras coisas como ponto de distância, dot dot. Eu estou indo só para se referir a este como a pilha na parte superior. E, em seguida, na parte inferior da imagem, para representar o principal, eu vou para dar-lhe uma memória fatias na pilha. Para f, eu vou dar-lhe uma fatia de memória na pilha. Agora, eu tenho que consultar meu código fonte novamente. Quais são as variáveis ​​locais para o principal? Aparentemente nada, então essa fatia é efetivamente vazio ou nem tão grande como eu desenhei isso. Mas, na f, eu tenho uma variável local, que é chamado de x. Então, eu estou indo para ir em frente e dar f um bloco de memória, chamando-x. E agora malloc de 10 vezes 4, Então malloc 40, onde está o memória vem? Nós não temos tirado uma foto como este antes. Mas vamos supor que é efetivamente vindo aqui, então um, dois, três, quatro, cinco. E agora eu preciso de 40 deles. Então eu vou fazer ponto, ponto, ponto de sugerir que há ainda mais memória voltando do heap. Agora, qual é o endereço? Vamos escolher o nosso arbitrária abordar como sempre - Ox123, embora ele provavelmente vai ser algo completamente diferente. Esse é o endereço do primeiro byte no memória que eu estou pedindo para malloc. Assim, em breve, uma vez que a linha 20 é executada, o que é literalmente armazenado dentro de x aqui? Ox123. Ox123. E o boi é desinteressante. Significa apenas que aqui está um número hexadecimal. Mas o que é fundamental é que o que eu tenho loja em x, o que é uma variável local. Mas seu tipo de dados, uma vez mais, é um endereço de um int. Bem, eu estou indo para armazenar Ox123. Mas, novamente, se isso é um pouco demais desnecessariamente complicado, se eu rolar para trás, podemos abstrair esta muito longe razoável e apenas dizer que x é um ponteiro para esse pedaço de memória. OK. Agora, a questão em apreço é o seguinte - linha 21, ao que parece, é buggy. Por quê? Desculpe? Ele não tem - dizer que uma vez mais. Bem, isso não acontece gratuitamente. Então esse é o segundo, mas. Portanto, há um outro, mas especificamente na linha 21. Exatamente. Este simples linha de código é apenas uma buffer overflow, uma saturação de buffer. Um buffer significa apenas um pedaço da memória. Mas esse pedaço de memória é de tamanho 10, 10 inteiros, o que significa que se índice nele usando o açúcar sintático de notação de matriz, a praça parênteses, você tem acesso a x suporte 0 x suporte 1 x, suporte de ponto, ponto, ponto. x suporte 9 é o maior deles. Então, se eu fizer x suporte de 10, onde Na verdade, estou indo na memória? Bem, se eu tiver 10 int - vamos realmente tirar tudo destes aqui. Então, essa foi a primeira de cinco anos. Aqui estão os outros cinco inteiros. Então x 0 suporte está aqui. x suporte 1 é aqui. x suporte 9 é aqui. x suporte 10 está aqui, o que significa que eu estou dizendo, na linha 21, o computador de inserir a número para onde? O número 0 para onde? Bem, é 0, sim. Mas só o fato de que sua 0 é uma espécie de coincidência. Poderia ser o número 50, para todos nós nos importamos. Mas estamos tentando colocá-lo no suporte x 10, que é o local onde esta ponto de interrogação é elaborada, que não é uma coisa boa. Este programa pode muito bem falhar como resultado. Agora, vamos em frente e ver se isso é, na verdade, o que acontece. Fazer memória, uma vez que o arquivo é chamado memory.c. Vamos em frente e correr a memória do programa. Então, nós tivemos muita sorte, na verdade, ao que parece. Nós tivemos sorte. Mas vamos ver se agora executar Valgrind. À primeira vista, o meu programa pode parece ser perfeitamente correcto. Mas deixe-me correr Valgrind com o - Vazamento de verificação é igual a plena memória. E agora, quando eu executar este - interessante. Inválido escrever de tamanho 4 a linha 21 do memory.c. Linha 21 do memory.c é qual? Oh, interessante. Mas espere. Tamanho 4, o que é que se refere? Eu só fiz uma gravação, mas é do tamanho 4. Por que é 4? É porque é um int, que é, outra vez, quatro bytes. Então Valgrind encontrado um bug que eu, olhando para o meu código, não o fizeram. E talvez o seu TF iria ou não. Mas o que Valgrind com certeza descobriu que fizemos um erro lá, mesmo embora nós tivemos muita sorte, eo computador decidiu, eh, eu não vou falhar só porque você tocou em um byte, uma o valor do int de memória que você não fez realmente possui. Bem, o que mais é buggy aqui. Endereço - este é um endereço de vista louco em hexadecimal. Isso significa apenas que em algum lugar na pilha é zero bytes após um bloco de tamanho 40 é alocado. Deixe-me afastar aqui e ver se isso é um pouco mais útil. Interessante. 40 bytes são definitivamente perdidos no registro de uma perda de 1. Novamente, mais palavras do que é útil aqui. Mas, com base nas linhas destacadas, onde eu deveria focar meu atenção para um outro bug? Parece que a linha 20 do memory.c. Então, se nós voltar para a linha 20, que é o aquele que você identificou anteriormente. E isso não é necessariamente buggy. Mas nós temos este inverteu seus efeitos. Então, como faço para corrigir pelo menos um desses erros? O que eu poderia fazer depois linha 21? Eu poderia fazer livre de x, por isso é para dar a volta essa memória. E como faço para corrigir este erro? Eu definitivamente deveria ir mais longe do que 0. Então deixe-me tentar e re-executar esta. Desculpe, definitivamente não mais do que 9. Fazer memória. Deixe-me reprise Valgrind em uma janela maior. E agora olhe. Nice. Todos os blocos de heap foram libertados. Sem vazamentos são possíveis. E lá em cima aqui, não há nenhuma menção mais do direito inválido. Só para ficar ganancioso, e vamos ver se outra demonstração não vai tão pretendido - Eu tive sorte de um momento atrás. E o fato de que este é 0 é talvez desnecessariamente enganosa. Vamos fazer 50 anos, um tanto arbitrária número, fazer memória memória dot slash - ainda ter sorte. Nada está falhando. Suponha que eu simplesmente fazer algo realmente tolo, e eu faço 100. Deixe-me refazer a memória, dot memória slash - teve sorte novamente. Como cerca de 1000? ints além de, aproximadamente, onde eu deveria estar? Fazer memória - caramba. [Risos] OK. Não vamos mexer mais. Reprise de memória. Lá vamos nós. Tudo bem. Então, aparentemente, você índice 100.000 ints além de onde deveria ter sido em memória, coisas ruins acontecem. Assim, este não é obviamente , uma regra rápida duro. Eu era uma espécie de utilizar julgamento e erro para chegar lá. Mas isso é porque, longa história curta, memória do computador também é dividido para estes segmentos chamados coisas. E, às vezes, o computador realmente deu-lhe um pouco mais de memória do que você pedir. Mas, para a eficiência, é apenas mais fácil obter mais memória, mas apenas dizer-lhe que você está recebendo uma parte dele. E se você tiver sorte, às vezes, portanto, você pode ser capaz de tocar memória que não pertence a você. Você não tem nenhuma garantia de que o valor você colocar lá vai ficar lá, porque o computador ainda pensa que não é seu, mas não é necessariamente vai para atingir um outro segmento de memória no computador e induzir a um erro como este aqui. Tudo bem. Todas as perguntas, em seguida, sobre a memória? Tudo bem. Vamos dar uma olhada aqui, então, a algo que temos vindo a tomar para concedido por algum tempo, o que É neste arquivo chamado cs50.h. Portanto, este é um arquivo. Estes são apenas um bando inteiro dos comentários em cima. E você pode ter olhado para isso se você remexia no aparelho. Mas verifica-se que o tempo todo, quando nós costumávamos usar string como um sinônimo, o meio pelo qual nós declaramos que era sinônimo com este palavra-chave typedef, para definição do tipo. E nós estamos dizendo essencialmente, fazer amarrar um sinônimo para a estrela de char. Que os meios pelos quais a pilha criou essas rodinhas conhecidos como a string. Agora aqui é apenas um protótipo para getchar. Poderíamos tê-lo visto antes, mas que é na verdade o que ele faz. getchar não tem argumentos, retorna um char. GetDouble não tem argumentos, retorna um double. GetFloat não recebe argumentos, retorna uma bóia, e assim por diante. getInt está aqui. getlonglong é aqui. E getstring está aqui. E é isso. Esta linha roxa é outro pré-processador directiva por causa do hashtag no início do mesmo. Tudo bem. Então, agora deixe-me entrar em cs50.c. E não vamos falar muito sobre isso. Mas para lhe dar um vislumbre do que está vem acontecendo tudo isso tempo, deixe-me ir para - vamos fazer getchar. Então getchar é mais comentários. Mas parece que isso. Portanto, esta é a função real getchar que temos sido tendo por certo existe. E mesmo que não use este que, muitas vezes, se alguma vez, é pelo menos relativamente simples. Então, vale a pena dar uma rápida olhada aqui. Então getchar tem um loop infinito, deliberadamente de modo aparentemente. Em seguida, chama - e este é um tipo de bom reutilização de código que nos escreveu. Ele chama getstring. Porque o que faz significa obter um char? Bem, assim como você pode tentar obter uma linha inteira de texto do usuário e em seguida, basta olhar para um desses caracteres. Na linha 60, aqui está um pouco pouco mais de um teste de sanidade. Se getstring retornou nulo, não vamos continuar. Algo deu errado. Agora, isso é um pouco chato, mas convencional em C. carbonizar max provavelmente o que representa apenas com base em seu nome? É uma constante. É como se o valor numérico do maior de char você pode representar com uma mordida, o que provavelmente é o número 255, que é o maior número que representam oito bits, a partir de zero. Então eu usar isso, nesta função, quando escrever este código, só porque se algo der errado em getchar mas seu propósito na vida é voltar a char, você precisa de alguma forma ser capaz para sinalizar ao usuário que algo deu errado. Nós não podemos retornar nulo. Acontece que nulo é um ponteiro. E, novamente, getchar tem para retornar um char. Assim, a convenção, se algo der errado, é você, o programador, ou em Neste caso, me com a biblioteca, eu tive a apenas decidir arbitrariamente, se algo der errado, eu vou retornar o número 255, o que é verdadeiramente significa que não pode, o usuário não pode digitar o caracter representado pela número 255, porque tivemos um roubá-lo como o chamado valor de sentinela para representam um problema. Agora, descobre-se que o caráter 255 não é algo que você pode digitar no seu teclado, por isso não é grande coisa. O usuário não percebe que Eu roubei esse personagem. Mas se você já viu nas páginas de homem em uma sistema de computador alguma referência a um todas as tampas constante como este que diz: em casos de erro esta força constante ser devolvido, isso é tudo que algum ser humano fez anos atrás, foi decidido arbitrariamente retornar esse valor especial e chamá-lo de uma constante no caso algo der errado. Agora a mágica acontece por aqui. Em primeiro lugar, eu estou declarando na linha 67 dois personagens, C1 e C2. E então, em linha 68, há realmente uma linha de código que é uma reminiscência de nosso amigo printf, uma vez que tem por cento Cs entre aspas. Mas note o que está acontecendo aqui. sscanf significa varredura string - significa digitalizar um formato string, sscanf ergo. O que significa isso? Isso significa que você passa para sscanf uma string. E linha é o que o usuário digita pol Você passa a sscanf uma seqüência de formato como isso que diz a scanf quais são Você está esperando que o usuário tenha digitado dentro Você, então, passar-nos os endereços de dois pedaços de memória, neste caso, porque eu tenho dois espaços reservados. Então eu vou dar-lhe o endereço de C1 e o endereço de C2. E lembrar que você dá em função da endereço de alguma variável, o que é a implicação? O que pode fazer essa função, como resultado de dar-lhe o endereço de um variável, ao contrário a própria variável? É possível alterá-lo, certo? Se você tivesse alguém um mapa para a física endereço, eles podem ir lá e fazer o que eles querem naquele endereço. A mesma idéia aqui. Se passarmos a sscanf, o endereço de dois pedaços de memória, mesmo estes pequenos pequenos pedaços de memória, C1 e C2, mas nós dizemos que o endereço deles, sscanf pode mudá-lo. Assim, o propósito de sscanf na vida, se lermos a página principal, é ler o que o usuário digitou, esperança para que o usuário tenha digitados em um personagem e talvez outro personagem, e tudo o que o usuário digitado, o primeiro personagem vai aqui, o segundo personagem vai aqui. Agora, como um aparte, isso, e se fosse só sei que a partir da documentação, o fato de eu colocar um espaço em branco lá Significa apenas que eu não me importo se o usuário pressiona a barra de espaço um pouco vezes antes que ele ou ela tem um personagem, eu vou ignorar qualquer espaço em branco. De modo que, eu sei que a partir de a documentação. O fato de que há uma segunda% c seguido de espaço em branco é realmente deliberada. Eu quero ser capaz de detectar se o usuário asneira ou não cooperar. Então, eu estou esperando que o usuário só digitado em um personagem, portanto, eu estou esperando sscanf que só vai voltar a valor 1, porque, mais uma vez, se eu ler a documentação, o propósito de sscanf em vida é devolver ao número de As variáveis ​​que foram preenchidos com a entrada do usuário. Passei em duas variáveis endereços, C1 e C2. Espero, porém, que apenas uma das deles é morto, porque se sscanf retorna 2, o que presumivelmente a implicação lógica? Que o usuário não apenas dar-me uma personagem como eu disse a ele ou ela. Eles provavelmente digitado no menos dois caracteres. Então, se eu, em vez não teve a segunda % C, eu só tinha um, que francamente, seria mais intuitivo abordagem, acho que a primeira vista, você não vai ser capaz de detectar se o usuário foi dando-lhe mais input do que você realmente queria. Portanto, esta é uma forma implícita de verificação de erros. Mas note que eu faço aqui. Uma vez que eu tenho certeza que o usuário me deu um personagem, eu liberar a linha, fazendo o oposto de getstring, que por sua vez usa malloc, e depois eu volto C1, o personagem que eu esperava que o fornecido pelo usuário e somente fornecido. Então, um rápido relance apenas, mas qualquer dúvida sobre getchar? Nós vamos voltar a alguns dos outros. Bem, deixe-me ir em frente e fazer isso - Suponha agora, apenas para motivar o nosso a discussão de uma semana, mais tempo, esta é um arquivo chamado structs.h. E, novamente, esta é apenas uma amostra de algo que está por vir. Mas note que um monte isto é comentários. Então deixe-me destacar apenas o parte interessante por enquanto. typedef - há essa mesma palavra-chave novamente. typedef que usamos para declarar cadeia como um tipo de dados especial. Você pode usar typedef para criar nova marca tipos de dados que não existiam quando C foi inventada. Por exemplo, int vem com C. carvão vem com C. dupla vem com C. Mas não há nenhuma noção de um estudante. E ainda seria muito útil para ser capaz de escrever um programa que armazena em uma variável, número de identificação do aluno, seu nome, e sua casa. Em outras palavras, três pedaços de dados, como um int e um corda e outra string. Com typedef, o que é muito poderoso sobre isso e a palavra-chave para sturct estrutura, você, o programador em 2013, pode realmente definir o seu próprio tipos de dados que não existiam anos atrás, mas que atendam às suas finalidades. E aqui, em linhas 13 a 19, estamos declarando um novo tipo de dados, como um int, mas chamando-o de estudante. E dentro desta variável vai ser três coisas - um int, string e uma corda. Então você pode pensar que é realmente aconteceu aqui, mesmo que este é um bit de uma simplificação para hoje, um aluno é essencialmente indo para ficar assim. Que vai ser um pedaço de com uma memória de identificação, um nome campo, e um campo de casa. E nós vamos ser capazes de usar esses pedaços de memória e acessá-los como se segue. Se eu entrar em struct0.c, aqui está uma relativamente longo, mas depois de um padrão, de código que usa esse novo truque. Então, primeiro, deixe-me chamar a sua atenção para as partes interessantes em cima. Afiada define três estudantes, declara um constantes chamadas de alunos e cessionários ele arbitrariamente o número 3, apenas então eu tenho três alunos que utilizam este programa por enquanto. Aí vem o principal. E note, como faço para declarar uma matriz de estudantes? Bem, eu só usar a mesma sintaxe. O estudante palavra é, obviamente, nova. Mas o estudante, classe, estudantes suporte. Então, infelizmente, há muito de reutilização de termos aqui. Este é apenas um número. Então, isso é como dizer que três. Classe é apenas o que eu quero para chamar a variável. Eu poderia chamá-lo de alunos. Mas classe, isto não é uma classe numa orientada a objetos Java tipo de caminho. É apenas uma turma de alunos. E o tipo de cada elemento de dados nessa matriz é estudante. Portanto, este é um pouco diferente e de dizer algo assim, é apenas - Eu estou dizendo que me dar três alunos e chamar essa classe array. Tudo bem. Ora aqui está uma de quatro loop. Familiarizado desse cara - iterate de zero a três, no máximo. E aqui está a nova peça de sintaxe. O programa vai me pedir, o ser humano, para dar-lhe um estudante ID, que é um int. E aqui está a sintaxe com a qual você pode armazenar algo no campo ID em localização classe suporte I. Então essa sintaxe não é nova. Isto significa apenas dar-me a oitava aluno da classe. Mas este símbolo é nova. Até agora, nós não pode ser usado ponto, pelo menos em um código como este. Isto significa ir para a struct conhecido como um estudante e colocar alguma coisa lá. Da mesma forma, nesta linha seguinte, 31, ir em frente e colocar o que o usuário digita um nome aqui eo que eles fazem para casa, a mesma coisa, vá em frente e colocá-lo em. casa. Então, o que faz este programa finalmente fazer? Você pode ver um pouco de provocação lá. Deixe-me ir em frente e fazem estruturas 0 dot barra struct 0, ID do aluno 1, diz David Mather, estudante ID 2. Rob Kirkland, estudante ID 3. Lauren Leverit - ea única coisa que este programa fez, que é apenas completamente arbitrário, é Eu queria fazer alguma coisa com esses dados, agora que eu já nos ensinou como usar estruturas, é que eu só tinha este ciclo extra aqui. Eu iterar sobre o conjunto de alunos. Eu usei o nosso, amigo talvez agora familiar, String de comparação, a stircomp cheque é a casa de 8 estudantes igual a Mather? E se assim for, basta imprimir algo arbitrariamente gosta, sim, é. Mas, novamente, apenas me dando oportunidades de utilizar e reutilizar e reutilizar esta nova notação de ponto. Então, quem se importa, certo? Chegando-se com um programa de estudante é um tanto arbitrária, mas acontece que podemos fazer coisas úteis com isto, por exemplo, como se segue. Esta é uma estrutura muito mais complicada em C. Tem uma dúzia ou mais campos, um tanto enigmaticamente chamado. Mas se você já ouviu falar de uma gráfica formato de arquivo chamado bitmap, BMP, ele Acontece que o formato de arquivo bitmap se parece muito com que este. É um pouco cara Smiley estúpido. É uma pequena imagem que eu tenho ampliado em muito grande para que eu pudesse ver cada dos pontos ou pixels individuais. Agora, acontece que pode representar uma ponto preto com, digamos, o número 0. E um ponto branco com o número 1. Portanto, em outras palavras, se você quiser chamar um Rosto sorridente e salvar a imagem em um computador, é suficiente para armazenar e zeros aqueles que se parecem com esta, onde, mais uma vez, os são brancos e zeros são negros. E juntos, se você efetivamente tem um cinge de uns e zeros, você tem um grade de pixels, e se você colocar -los, você tem um bonito rostinho Smiley. Agora, o formato de arquivo de bitmap, BMP, é efetivamente que, sob o capô, mas com mais pixels sot que você pode realmente representar as cores. Mas quando você tem mais sofisticado formatos como JPEG e BMP e GIF com o qual você pode estar familiarizado, aqueles arquivos no disco normalmente não só tem zeros e uns para os pixels, mas eles têm alguns metadados, bem como - meta no sentido de que não é realmente dados, mas é útil para ter. Então, esses campos aqui são o que implica, e vamos ver isso com mais detalhe na P-set 5, que antes dos zeros e uns que representar os pixels de uma imagem, há um monte de metadados como o tamanho da imagem e o largura da imagem. E notem que eu estou arrancando fora de alguns coisas arbitrárias aqui - largura e altura. Contagem de bits e algumas outras coisas. Portanto, há alguns metadados em um arquivo. Mas por entender como os arquivos são colocados fora dessa forma, você pode realmente em seguida, manipular imagens, recuperar imagens do disco, redimensionar imagens. Mas você não pode necessariamente melhorá-los. Eu precisava de uma fotografia. Então eu voltei para RJ aqui, que você viu na tela há algum tempo atrás. E se eu abrir Keynote aqui, este é o que acontece se você tentar ampliar e melhorar RJ. Ele não está ficando melhor realmente. Agora Keynote é uma espécie de esbater-se um pouco, apenas para encobrir o facto de RJ não fica particularmente maior quando você zoom in E se fizer dessa forma, ver as praças? Sim, você pode definitivamente ver os quadrados em um projetor. Isso é o que você começa quando você melhorar. Mas no entendimento de como o nosso RJ ou o Smiley face é implementado nos deixa realmente escrever o código que manipula essas coisas. E eu pensei que eu ia acabar com esta nota, com 55 segundo de uma melhorar isso, Atrevo-me, por exemplo, em vez enganosa. [REPRODUÇÃO] -Ele está mentindo. Sobre o quê, eu não sei. -Então, o que nós sabemos? -Isso às 9:15 Ray Santoya estava no caixa eletrônico. -Então, a pergunta é o que que ele estava fazendo em 9:16? Tiro-a nove milímetros em alguma coisa. Talvez ele viu o atirador. -Ou foi trabalhar com ele. -Espere. Volte um. -O que você vê? -Trazer o rosto, tela cheia. -Seus óculos. -Há uma reflexão. -Esse é o time de beisebol Neuvitas. Esse é o seu logotipo. -E ele está falando com quem quer que esteja usando aquela jaqueta. [FIM REPRODUÇÃO DE VÍDEO] DAVID J. MALAN: Isto ser Problem Set 5. Vamos vê-lo na próxima semana. Falante masculino: Na próxima CS50. [Grilos cantando] [Música tocando]