COLUNA 1: Olá a todos. Vamos começar. Acho que as pessoas ainda estão indo ser filtrando. Mas, no interesse de tempo, para que possamos obter vocês daqui na hora certa, vamos começar. Então bem-vindo ao CS50 quiz 0 avaliação. Para aqueles de vocês que ainda não percebeu no entanto, você tem uma pergunta na quarta-feira. Woo-hoo. Se você ainda não começou a estudar ainda ou não perceberam que isto existe ainda, quizzes passadas e todas as informações sobre seu questionário estão no cs50.net/quizzes. Há algumas coisas muito boas por lá, quizzes últimos dos últimos 10 anos, bem como informações sobre este quiz e temas que vai ser coberta. Então, vamos começar. Então vocês devem se lembrar, o primeiro dia de aula David tinha essas lâmpadas por diante. Então, basicamente, tudo o que acontece sob a capa de um computador é feito em binário. Binário significa o que soa como, 0 e 1 do. Ela tem dois valores pode ser representada. Assim como no primeiro dia de seção quando David acendeu uma luz lâmpada para representar em, ou 1, o nosso computador entende como binário 0 e 1 de, ligado ou desligado. Noções básicas de binário. Cada lugar é representado na base de dois. Então você adiciona 2 a 0 para o 1 a 2 por todo o caminho para cima. Para calcular o seu binário é decimal, basta seguir esta equação Tipo de coisa. Se você tem um 1 em qualquer um desses lugares, você multiplicá-lo por tudo o que baseá-lo está, adicioná-lo para cima, e você começa a decimal. Então é assim que você contar a 5 em binário. Assim como o que estávamos fazendo no último slide, isto é como se fosse representam de 1 a 5. Da mesma forma, assim como você pode adicionar e subtrair em decimal ou base 10, ou realmente alguma base, em pode adicionar e subtrair em binário. Exatamente o que você pode esperar quando você adicionar os dois para cima, se ele é igual a maior que 1, você carrega a 1, torná-lo um 0, e fazer a adição dessa maneira, apenas como seria de esperar com regulares decimal ou qualquer outra base. Legal. Então, como eu disse antes, tudo o que continua sob a capa de nosso computador é feito em 0 e 1 do, ou binário. Então, como podemos expressar, por exemplo, letras ou números ou caracteres? E a resposta para isso é ASCII. ASCII é um mapeamento entre os caracteres que nós normalmente vemos no Idioma Inglês como a, B de, Cs, sublinhado, traços, e qualquer coisa assim. E ele mapeia isso para um valor ASCII. Um valor ASCII é apenas um número que pode ser entendido pelo computador. E, assim como você pode fazer a adição e subtração com números, você pode fazer los com valores ASCII. Portanto, neste exemplo, o que isso vai imprimir? Sim, por isso apenas um espaço B espaço espaço C D. Onde meu mouse ir? Observe que você pode definir um int a 65. E quando você imprime que utilizando por cento C, vai interpretar isso como um caráter e irá imprimir A. Da mesma forma, você pode declarar lo como um char. E quando você imprimi-lo usando cento C, que vai interpretar isso como por cento D. E, assim como você pode adicionar um número, você pode adicionar personagens são Valores ASCII, neste caso. Então, um pouco ponteiro para todos. 5, como uma string, não na verdade, ser igual a 5. Então, como podemos converter o corda 5 para o inteiro 5? Alguma ideia? Sim. Então, se temos 5 como uma string, podemos subtrair 0. E isso vai nos dar 5. E da mesma forma, se tivermos 5 como um inteiro, acrescentar que para a seqüência 0. E isso nos dá a corda 5. Legal. Agora, lembre-se de volta para lecionar um onde falamos sobre algoritmos. Então, como é que vamos realmente quer um computador para fazer coisas interessantes? Você sabe, só somar e subtrair números e imprimir coisas fora não é que emocionante. Normalmente, queremos que o nosso computador para realizar algum tipo de algoritmo. Algo um pouco mais complexa que apenas aritmética simples. Um algoritmo é apenas um passo a passo conjunto de instruções sobre como realizar um certo task-- Assim como uma receita. Você deve se lembrar do primeiro dia de classe onde David tinha nos contar um quarto de pessoas e quantas pessoas no quarto. Você pode ser usado para contagem uma por uma. 1, 2, 3, 4. Nesse caso, um algoritmo de tempo linear. Mas David introduziu um algoritmo para você contar as pessoas na sala onde todo mundo se levanta, você diz que seu número para outra pessoa, acrescentar que número para cima, e uma pessoa se senta. E você repetir isso. Isso é um tipo de algoritmo. Podemos analisar uma forma eficiente algoritmo é baseado no que é tempo de execução. Mas vamos falar um pouco mais sobre isso mais tarde. Assim, todos os algoritmos também pode ser escritos em pseudocódigo. Pseudocódigo é apenas um Inglês como sintaxe utilizada para representar uma linguagem de programação. Por exemplo, se quiséssemos pedir um usuário adivinhar o meu número favorito, nós pode ter pseudocódigo como tal. Obter um usuários adivinhar. Se o palpite estiver correcto, diga-lhes estão corretas, senão dizer-lhes eles não estão corretos. Pseudocódigo e é uma forma de facilmente representando uma idéia ou um algoritmo. Então agora podemos querer realmente escrever isto na linguagem que o computador pode compreender. Então, podemos escrever nosso pseudocódigo e interpretar que no código-fonte. Até agora, o código fonte devem aderir para uma determinada sintaxe uma linguagem de programação. E até agora, na CS50, temos usado principalmente c. Portanto, este pode ser o código fonte para c. Mais tarde no curso, você noite vem em contato com outros programas linguagens como PHP. Ou se você ainda tomar outras classes, você pode fazer Java, Python, ou mesmo OCML. Mas em nossa linguagem de programação C, este é como podemos escrever o código-fonte o algoritmo que pseudocódigo Eu só descrito anteriormente. Então como é que o computador realmente entender isso? Como eu disse antes, isso só realmente entende zeros e uns. Então como é que começa a partir da fonte código para algo que pode ser compreendidos? Bem, nós temos algo chamado compilador. Se você se lembrar de volta na maior parte de seu Série de Exercícios, você teve algum tipo de programa escrito num ficheiro de ponto c. E então você deve digitar make. Então, o que é fazer a fazer? Você pode digitar make para compilar seu programa porque someone-- quem escreveu seu conjunto p; provavelmente David-- criou um arquivo make. E que diz fazer saber para executar o seu compilador, chamado clang, que a vontade em seguida, compilar o código fonte para objeto de código, que é zeros e uns que o computador entende. Mas um pouco mais tarde, iremos mais em profundidade sobre compiladores. Então lembro pset 0, onde-- sim, Você tem uma pergunta? AUDIÊNCIA: [inaudível]? COLUNA 1: Sim. Eu acho que eles realmente deve ser online. Sim. AUDIÊNCIA: É como o [inaudível]? COLUNA 1: Não é. O são em cs50.net/quizzes. AUDIÊNCIA: quizzes Slash, barra de 2013, reduzir 0, e só clicar quizzes 2013 e teste 0, rever os slides da seção. COLUNA 1: Sim, por isso, se vocês querem arrancá-la e analisá-la em seu próprio computador, tudo bem também. Diga isso de novo. AUDIÊNCIA: [inaudível]. COLUNA 1: Sim, [inaudível] é a variável dummy. Ah, sim? AUDIÊNCIA: [inaudível]? Palestra 1: Não, greves não estão no exame. Desculpe, sua pergunta foi, foi greves no exame. E não é. Então pset 0, vocês devem ter tudo implementado algo usando zero. E aprendemos alguma programação básica blocos de construção que utilizam zero. Então, vamos dar uma olhada em alguns destes blocos de construção que compõem um programa. A primeira é a expressão booleana. As expressões booleanas são queridos e 0s ou qualquer coisa que tem dois valores possíveis. Neste caso, verdadeiras ou falsas, ligado ou desligado, e sim ou não. Um exemplo de um método simples, muito simples, programa que usa um valor booleano expressão aqui. Então, para expressões booleanas para ser útil, temos operadores booleanos. Estes são os operadores que podem ser utilizados para comparar os valores determinados. Então, temos ou não e igual, menos ou igual a, ou maior do que igual a, e menos de ou superior. Mas estes operadores não são muito úteis a menos que possamos combiná-los em condições. Então vocês podem se lembrar do zero e para o seu p define que tinha condições. Eles são, essencialmente, como garfos a lógica do seu programa que executa consoante uma condição for atendida. Portanto, uma das condições que tínhamos usado muitas vezes neste curso é a se, então, se, e as condições de outra pessoa. Aqui está um exemplo de como você pode usar isso. Alguém sabe a diferença entre apenas usando if todos o caminho versos if, else, se, e outra coisa combinada? Sim? AUDIÊNCIA: [inaudível]. COLUNA 1: Exatamente. Então, se eu tivesse se todo o caminho até este forma, mesmo se essa condição retorna verdade, ele ainda vai continuar testar os dois seguintes. Considerando que, com um-se mais, uma outra declaração, se o que retorna true, os outros não são testados. Qualquer dúvida sobre isso? Legal. Então você usa um else if-de uma outra pessoa declaração, se você sabe que ele só pode ser um desses casos. Então, nós sabemos, se x é menor que 0, é definitivamente não vai ser maior do que 0. Em seguida, um outro bloco de construção que aprendemos são loops. Temos três tipos de loops. Para loops, while, e fazer enquanto loops. E geralmente, quando você se senta para escrever algo, você tem que decidir qual dos três você quer usar. Então, como vamos decidir qual deles? Geralmente usamos um loop for, se soubermos quantas vezes queremos fazer uma iteração por algo ou quantas vezes queremos executar uma tarefa. Nós usamos loops while se precisamos de alguma condição para ser verdade para continuar correndo. E usamos fazer enquanto muito semelhante ao tempo, mas nós queremos que nosso código seja executado em pelo menos uma vez. Então fazer enquanto, o que está no fazer a vontade sempre executado pelo menos uma vez. Considerando que, com o tempo, ele pode não funcionar em todos, se o condição não for satisfeita. Qualquer dúvida com isso? Assim, a estrutura de um loop for. Vocês já devem ter visto isso. Você inicializa-lo. Você tem algum tipo de condição. Assim, por exemplo, podemos inicializar como para i é igual a 0. i é menos do que 10. E i ++. Uma muito simples que nós fizemos. Para um loop while, da mesma forma, você tem ter algum tipo de inicialização, algum tipo de condição, e algum tipo de atualização. Assim, podemos implementar o nosso laço for também como um loop while usando isso. E da mesma forma com um loop Do While, poderíamos ter alguma inicialização, executar algo, atualizá-lo e em seguida, verificar a condição. Então agora funções. Nós colocamos tudo junto. Podemos querer escrever alguns tipo de função. Função comuns que você pode Já vimos é o principal. Principal é uma função. Ele tem um tipo de retorno, int. Ele tem um nome de função, a principal. E tem argumentos, argc e argv. Então principal é apenas uma função. Outras funções que você poderia ter usado, printf printf-- é um function-- GetInt, toupper. Mas estes acontecer de ter sido implementado por nós algum tipo de biblioteca. Se vocês lembram, incluindo esta biblioteca ou a CS50.h E / S padrão da biblioteca. Sim, questionar? AUDIÊNCIA: É principal apenas inerente c? Será que apenas uma espécie de [inaudível]? COLUNA 1: A questão é se principal é inerente em c. E sim, todas as funções têm uma função principal. É uma espécie de necessário para o computador para saber por onde começar execução do código. AUDIÊNCIA: Então você não iria [inaudível]? COLUNA 1: No. Alguma outra pergunta? Legal. Então, assim como você pode usar uma função que está escrito para você, você também pode escrever sua própria função. Esta é uma função que alguém pode Escrevi para calcular o volume de q, por exemplo. Há um tipo de retorno aqui, neste caso int, nossa q nome da função e nosso lista de parâmetros. E note que você tem que escrever os dados tipo do parâmetro que você deseja ou então utilizar a função não faz saber que tipo de parâmetro que deve ser aceita. Então, neste caso, nós queremos um número inteiro como o nosso contributo. Então, por que poderíamos querer usar funções? Primeiro de tudo, ótimo para organização. Eles ajudam a quebrar o seu código em pedaços mais organizado e fazer mais fácil de ler. Simplificação. Isso é bom para o projeto. Quando você está lendo um pedaço de código ea função principal é, realmente, muito longo, pode ser mais difícil de raciocinar sobre o que está acontecendo. Então, se você dividi-la em funções, pode ser mais fácil de ler. E reutilizá-capacidade. Se você tem um pedaço de código que está sendo chamado ou executado várias vezes, em vez de reescrever esse código 10 vezes na sua função principal, que você pode quer reutilizá-lo. E então, toda vez que você precisa para usá- pedaço de código, chamar a função. Então, agora, se nos lembrarmos de volta para zero, nós também falou sobre alguns conceitos, uma das quais é uma rosca. Tópico é o conceito de múltiplo seqüências de código executando ao mesmo tempo. Então, acho que volta para um dia em que David tinha vocês contarem o número de pessoas na sala. Essencialmente, o que estava acontecendo é sobre todos vocês foram executando segmentos separados. E esses tópicos foram se reunindo para obter algum tipo de resposta. Da mesma forma, em risco, quando você tem vários sprites, você pode tenho um gato e um cachorro. E eles seriam simultaneamente executando seus próprios scripts. Isso é um exemplo de segmentação. E o outro conceito que foi foi introduzido em zero eventos. E os eventos são quando várias partes do seu código de comunicar uns com os outros. No início, essa foi quando você usou o controle da transmissão e da Quando eu Receba blocos. E também, no Conjunto de Problemas 4, vimos um pouco de eventos também. Vocês poderiam ter usado a biblioteca Gevent. E não era uma função waitForClick em que você estava esperando para que o usuário clique. E o seu clique, neste caso, seria o evento e esperar por clique é o seu manipulador de eventos. E também, ao longo de executar seus Série de Exercícios e trabalhar em suas Série de Exercícios, você pode ter entrado em contato com alguns desses comandos. Isto é o que você digitou em seu janela de terminal ou o que quer que a janela que aparece em sua edição para g, essencialmente, navegar no seu computador. Assim, por exemplo, LS lista o conteúdo de um diretório. Faça diretório cria uma nova pasta. CD, altere o diretório. RM, remover, excluir um arquivo ou algum diretório. E, em seguida, remover o diretório remove um diretório. AUDIÊNCIA: [inaudível]? COLUNA 1: Sim, com certeza. Desculpe, a pergunta era se sugiro colocar este sobre a folha de fraude. Poderia ajudar. Se você tiver espaço, você pode colocá-lo. Também é apenas geralmente bom o suficiente de lembrar, porque quando você usá-lo você pode querer apenas ter memorizado. Isso vai tornar sua vida muito mais fácil. Será que eu responder a sua pergunta? Então, agora, nós conversamos um pouco brevemente sobre bibliotecas. Mas as duas principais que temos sido usando até agora no curso são padrão I / O e CS50. Que tipo de coisas estão incluídas na biblioteca padrão I / O? Sim, até agora nós usamos printf. Em CS50, usamos GetInt e GetString. E a seqüência de tipo de dados também acontece a ser declarado nesta biblioteca CS50. Vamos falar um pouco mais em profundidade sobre como as bibliotecas funcionam e como eles interagir com o resto do seu código. Mas essas são as duas principais que ter entrado em contacto com a medida em o curso. Tipos. Estes são bons para lembrar o quanto cada tipo está representado por ou como muitos bytes cada tipo de requires-- int, 4 bytes; char, um byte. Float é de 4 bytes. O que é um casal? AUDIÊNCIA: [inaudível]. COLUNA 1: É, portanto, um flutuador mas o dobro do tamanho. Que tal um tempo? AUDIÊNCIA: [inaudível]. COLUNA 1: OK. O que é um tempo? AUDIÊNCIA: [inaudível]. COLUNA 1: Sim, o dobro de um int. Sim. AUDIÊNCIA: [inaudível]. COLUNA 1: Long [inaudível]. E depois de um longo tempo é o dobro disso. AUDIÊNCIA: Não, não. Uma longa é apenas um int. Depende da arquitetura antes que o [inaudível] int e têm o mesmo tamanho. [Inaudível]. COLUNA 1: Então, um longo e um int são os mesmos. E depois de um longo tempo é o dobro do int. Legal. E então, qual é o último tipo? AUDIÊNCIA: Pointer. COLUNA 1: Sim, por isso, aprendemos um pouco sobre ponteiros. E, independentemente do que um ponteiro é apontando para-- poderia ser uma estrela de char ou um int star-- é sempre 4 bytes para um ponteiro. Perguntas sobre isso? Sim? AUDIÊNCIA: [inaudível]? COLUNA 1: Então, um longo e um int são o mesmo neste aparelho CS50. AUDIÊNCIA: O aparelho está completamente permutáveis. COLUNA 1: Yeah. Então, depois um longo tempo é o dobro de um int. AUDIÊNCIA: Este é o 32 bits? COLUNA 1: 32 bit, sim. AUDIÊNCIA: Então, [inaudível]? COLUNA 1: Sim, se isso não acontecer explicitamente dizer, você deve assumir um pouco 32. AUDIÊNCIA: Ele diria algo como assumindo um Arquitectura como o aparelho. Para 64 bits, as únicas coisas que mudança são longos e ponteiros. Ambos [inaudível]. COLUNA 1: Sim? AUDIÊNCIA: Pergunta. Assim, em um dos testes práticos, ele pergunta sobre um unsigned int. Então, como isso seria determinado a partir de um int [inaudível]? COLUNA 1: Um unsigned em também é 4 bytes. Mas o que é diferente sobre a assinatura int e um unsigned int? AUDIÊNCIA: [inaudível]. COLUNA 1: Certo. Pode-se representar os valores negativos. Mas como fazer isso? AUDIÊNCIA: [inaudível]. COLUNA 1: Sim, ele salva um bit para representar o sinal. A assinatura tem um pouco que representa o sinal. E não assinado apenas é todos os aspectos positivos. AUDIÊNCIA: OK. Então você diz que a dupla é duas vezes o tamanho de um flutuador? COLUNA 1: Dupla é duas vezes o tamanho de um flutuador, sim. AUDIÊNCIA: Como é que um ponteiro para um longo [inaudível]? COLUNA 1: Então a questão é como é que o ponteiro para uma longa long-- como é que apenas quatro bytes quando um longo seus 8 bytes. Então lembre-se que é um ponteiro, essencialmente, pelo valor muito base. AUDIÊNCIA: [inaudível]. COLUNA 1: Sim, então um ponteiro é apenas um local de memória. Por isso, não importa o quanto de espaço esse ponteiro está apontando. Ele só precisa de 4 bytes para acompanhar de que a localização de memória. Alguma outra pergunta? Legal. Assim, a última coisa que eu tenho é a saída padrão. Você deve usá-los com freqüência o suficiente para que você possa lembrar. Mas isso é quando usamos printf, por exemplo. E nós temos esses espaços reservados que foram chamados códigos de formato. Então por cento c char, i por cento para int, e também podemos usar por cento d. É a mesma coisa. Mas, em geral, em que CS50 tente usar por cento i. Porcentagem f para float. Ld por cento por muito tempo e por cento s para string. Da mesma forma, temos vindo a utilizar alguns dessas seqüências de escape. Por exemplo, barra invertida n para nova linha. Este é apenas para quando você está formatando seu código para impressão f. Sim? AUDIÊNCIA: Qual é a percentagem de d? COLUNA 1: Então a questão é o que é por cento d para? Porcentagem d é para ints. Porcentagem d e i por cento são os mesmos. AUDIÊNCIA: Qual é a diferença entre barra invertida n e barra invertida r? COLUNA 1: Então a questão é, qual é o diferença entre o n e a folga r reação? Acho barra invertida r é-- AUDIÊNCIA: Então barra invertida r apenas implica retorna ao início da linha sem realmente ir para uma nova linha. Então, se você imprimir uma barra invertida r e você voltar para o início da linha em seguida, imprimir mais coisas, você sobrescrever o material que já está no [Inaudível]. Considerando que, na verdade, n vai para uma nova linha e vai para o [inaudível]. COLUNA 1: Bem, alguma pergunta? Tudo certo. Vou entregá-lo a Dan, que vai continuar. [Aplausos] DAN: Tudo bem. Então, eu vou estar falando de outro grande gama de idéias da classe que são aproximadamente representante de duas semanas e o início da terceira semana começando com fundição, que é apenas uma forma de tratamento de um valor de um determinado tipo, como um valor de um tipo diferente. Assim, podemos fazer isso com caracteres para ints, carros alegóricos para ints e longs longos para o dobro. Todas estas coisas podem ser utilizadas como formas para o tratamento de algum valor numérico menos de char como algum outro valor numérico. Portanto, há algumas questões com este, de Claro, o que acontece quando você joga coisas como bóia para ints. Então, isso é um pouco estranho. Temos um carro que é de 1,31. Nós multiplicá-lo por 10 mil. E, então, imprimi-lo como um int. O que é que esta saída? 10.000 vezes 1,31. Assim 13000, que é a estimativa? AUDIÊNCIA: Eu acho que é 10.000. DAN: Então, eu estou multiplicando-o por 10.000 antes que eu estou lançando-lo. AUDIÊNCIA: Oh. Não haveria um 9 e alguns números de 0? DAN: Você pode ter alguns dígitos estranhos. Tão certo, que é 1,3 vezes 10.000. Então é 13.000. E este weird-- adicional PÚBLICO: 13.100. DAN: 13.100. Obrigado, Rob. E este weirdness-- adicional este 9,9-- é simplesmente porque este elenco acabou arredondamento onde ele não deve ter. Sim. AUDIÊNCIA: O casting acontece depois de mais alguma coisa? DAN: Então porque eu tenho isso por escrito, que faz isso antes de multiplicação faz isso casting. AUDIÊNCIA: [inaudível]. DAN: Eu acho que seria lançado em primeiro lugar, sim, o que seria 10.000. Algo mais? Legal. Portanto, esta é 13.099. Por que isso acontece? A imprecisão. Carros alegóricos não são perfeitos. Eles só podem representar números a um certo número de algarismos significativos. Então, se nós imprimir 8 figos sig em este float, temos uma espécie de número olhando feio. E isso é porque 1,31 não pode com precisão ser representados por simples potências de dois na máquina. Por isso, acaba tendo o mais próximo acho que, o que acaba ser um pouco baixa. Faz sentido? Está bem. Agora, mudou são uma forma diferente de fazendo declarações condicionais em que todos os que nos interessa é a única variável. Portanto, neste exemplo particular, estamos recebendo um número inteiro do usuário. E então, nós estamos olhando para o que esse inteiro é. Presumivelmente, ele é o número entre um e quatro. Isso é o que estamos pedindo. Então você faz uma mudança de o nome da variável. Em seguida, você configura os casos de possível valores que poderia ser. Então caso de um, digo que é baixa. E então você quebra para sair da condição chave para que você não continuar. Na próxima caso-- assim caso dois e caso três-- se for caso dois apenas cai para a primeira linha de código que vê como com caso, três, até que vê uma pausa. Portanto, a razão que você começa um caso para só impressão baixo é porque eu ter essa pausa aqui. Se eu, por exemplo, ignorou essa break-- se eu joguei este breakaway-- seria imprimir baixa, e então seria imprimir meio, e, em seguida, ele iria quebrar. Então breaks são uma parte importante de mudar as condições e eles devem estar lá. Os casos que não sejam reconhecidos explicitamente são tratados pelo padrão caso no interruptor e deve ser lançado. AUDIÊNCIA: So 1, 2, 3, e 4 seriam n? DAN: Os valores que n pode ser. Sim. Sim? AUDIÊNCIA: Então, quando você tem que [inaudível]? DAN: Você iria imprimir baixo, e em seguida seria imprimir meio, e em seguida, ele iria quebrar. AUDIÊNCIA: Por que ele iria imprimir meio que [inaudível]? DAN: Então, tudo sob um caso antes de uma pausa se enquadra. Assim, caso uma impressão é caso sob um tal como a presente na sequência de impressão. Sim? AUDIÊNCIA: [inaudível]? DAN: Então esse número é apenas uma especial valor que esta variável pode tomar, certo? Será que isso faz sentido? Sim. AUDIÊNCIA: [inaudível]? DAN: Sim, caso dois iria imprimir meio e, em seguida, romper. AUDIÊNCIA: [inaudível]? DAN: Eu acho que qualquer? Que outros tipos de dados você pode passar? AUDIÊNCIA: Você pode alternar sobre quaisquer tipos de dados. Mas isso só significa alguma coisa mais caracteres e ints e coisas assim, porque se você estiver migrando um ponteiro que realmente não faz sentido, comutação de cargas, se ele ainda vamos você faz isso, por causa de ponto flutuante em precisão, você realmente não quero fazer isso de qualquer maneira. Então, basicamente, apenas inteiros e caracteres e coisas assim. DAN: Sim, é quando você tem explícita valores que você sabe, eu acho, pode ser que a mudança é realmente útil. Boa? Está bem. O escopo é o intervalo que a declarada variável estende. Então neste pequeno pedaço de código que eu tenho, seria cheio de erros. E a razão é eu declarei isso int i dentro do escopo deste loop. E então eu estou tentando fazer referência que i fora desse âmbito de loop. Então, basicamente, você pode pensar sobre o escopo como qualquer coisa que você declarar com dentro de um conjunto de chaves só existe dentro dessas chaves. E se você tentar usar essa variável fora dessas chaves, você obter um erro do compilador. Sim? AUDIÊNCIA: Então este não funciona? DAN: Esta funcionalidade não funciona, sim. Cordas. String a char *. Eles são exatamente o mesmo. Eles são apenas apontadores para caracteres. E quaisquer caracteres que deve terminar com barra invertida zero, que é apenas uma convenção c. Ele é chamado o terminador nulo. E NULL-- N maiúsculo, capital de U, o capital L, o capital eu-- não é o mesmo que o Terminador NULL. Este é um ponteiro. Este é um personagem. Eles são muito distintas. Lembre-se disso. Será no questionário, provavelmente. Eu não vi o questionário. Sim? AUDIÊNCIA: Então NULL é, digamos, o ponteiro? DAN: Sim. AUDIÊNCIA: O que [inaudível]? DAN: Se, por exemplo, malloc é chamado quando você não tem memória suficiente para obter o tamanho que você está pedindo, malloc retornará NULL. É, basicamente, sempre que uma função é deve retornar um ponteiro, você preciso verificar contra NULL porque NULL é um bom-- muito é, mais ou menos, o valor de lixo. É um zero na medida em que os ponteiros vão. Sempre que você chamar uma função, que retorna um ponteiro. Você vai querer verificar-se Certifique-se de que esse ponteiro não é NULL porque NULL é muito comum. É uma espécie de retorno lixo. Então, se alguma coisa não vai bem, só retornam NULL no lugar. AUDIÊNCIA: [inaudível]? DAN: Sim, e isso é isso. AUDIÊNCIA: [inaudível]? DAN: Spell-lo como este. É o terminador NULL. É minúscula N-U-L-L se você soletrá-la. AUDIÊNCIA: E eu só fui trás e testou. E se você tentar colocar um ponto flutuante valor em um switch, ele vai gritar com você dizer, indicação requer expressão do tipo inteiro. DAN: Lá vai você. Mas sim, o que era a pergunta? AUDIÊNCIA: [inaudível]? DAN: Então o capital N, capital de U, o capital L, L maiúsculo é uma coisa real c. É o ponteiro nulo e apenas ser tratado como tal. Você nunca vai tentar soletrar o Caractere NULL e ver qualquer outra forma que não esta. Sim? AUDIÊNCIA: Então voltando para char max ou algo nas notas, seria encarnam a mesma função como [inaudível]? AUDIÊNCIA: Então você está se referindo a retornando de char máximo de getchar, ou seja o que for? AUDIÊNCIA: Yeah. AUDIÊNCIA: Sim, então o general prazo para todas essas coisas são valores sentinela. Assim como voltar int max de GetInt e Charlotte máximo de getchar, é deveria ser assim, tudo bem, se essas coisas estão voltando para nós, algo deu errado. Para ponteiros, que só acontecerá a ter este valor de sentinela que todos concorda em cima. E esta é a coisa que você retornar quando as coisas dão errado. Então Char max é o que estamos usando para representar algo como NULL ou getchar. AUDIÊNCIA: Então, se você está testando getchar, você poderia apenas colocar NULL? Teria que fazer a diferença? DAN: Você pode não apenas verificar NULL. Você teria que verificar caractere máximo porque o valor de retorno da função é um caráter não um ponteiro. Sim? AUDIÊNCIA: Esta pergunta para o comprimento da corda. Isso inclui o caractere NULL? DAN: No. E isso é, na verdade, como comprimento da corda sabe que parar porque ele passa por seu conjunto de caracteres até ele vê um personagem NULL. E então como é, tudo bem, eu sou feito. AUDIÊNCIA: [inaudível] cinco? DAN: Olá seria cinco. Yep. Então matrizes são contínuas blocos de memória. Eles têm acesso instantâneo ao dizer que o nome da matriz e, em seguida, em crespos suspensórios, qualquer que seja índice que você quer ir para, eles estão indexados a partir de zero a o comprimento de matriz menos 1. E eles estão declarados pelo tipo de coisa que você está armazenando no matriz, o nome da matriz, e então qualquer que seja o tamanho é de que matriz. Portanto, esta é uma matriz de caracteres de comprimento seis que tem esses valores. Sim? AUDIÊNCIA: [inaudível]? DAN: Yeah. AUDIÊNCIA: [inaudível]? DAN: Se você tem o que está acontecendo para a matriz já fez. Então, você pode especificar isso em vez de, digamos, char, qualquer que seja o nome do seu matriz é, colchetes vazios igual crespos prepare-H vírgula por vírgula E L L vírgula por vírgula O vírgula caráter NULL e chaveta. Isso também funciona como uma declaração. AUDIÊNCIA: [inaudível]? DAN: Então você precisa ter o tamanho já feito. AUDIÊNCIA: [inaudível]? DAN: Sim. Tudo bem. Argumentos de linha de comando são uma forma de recebendo entrada do usuário como argumentos para principal. Principal tem dois argumentos. O número de argumentos que está sendo passou ao longo da linha de comando e um vetor de strings ou uma matriz de cadeia de todos os argumentos. Então, se eu, por exemplo, chamada de função, como um ponto fora um espaço, espaço 2, três, argc seria 4. E o argv 0 seria um ponto fora. Argv1 seria 1. argv2 seria 2. argv3 seria 3, nesse caso particular. Sim? AUDIÊNCIA: [inaudível]? DAN: O último elemento do array porque a matriz é o comprimento argc mais um dos argb, o último elemento é o ponteiro NULL. É argc mais 1. Assim, no caso que eu acabei de dizer, ele seria argv 0 é um ponto fora. argv 1 é 1, 2 é argv2 argv 3 é 3. argv 4, que é uma maior argc que seria NULL. E isso é o ponteiro NULL. Sim. E isso é porque cadeia é uma estrela char é um ponteiro. Por isso, tem de ser do mesmo tipo. Sim? AUDIÊNCIA: Duas perguntas. Então, um, qual é a diferença entre isto e GetString outro do que um tipo no mecanismo de utilizador? E dois, ele é armazenado dentro sua memória recente? Assim como, GetString faria ser [inaudível]? DAN: Onde é armazenado? Eu não sei onde ele está armazenado. AUDIÊNCIA: Então, na verdade, você sabe como qualquer função que você chamá-lo de argumentos são armazenadas na pilha? Então argc e argv são argumentos para o main e eles estão na pilha, ou realmente logo acima o que você pensa como o início da pilha. Qual era a outra parte de questão? AUDIÊNCIA: Então, qual é o [inaudível]? DAN: Sim, é apenas uma forma diferente de obter a entrada do usuário. Isto de um pouco mais eficiente e é mais útil para scripts porque você pode apenas passar argumentos para o seu principal função, em vez de ter que esperar para os usuários, se você não tem quaisquer usuários. AUDIÊNCIA: E sim, obter cordas seria [inaudível]. Seria armazenar o material que você precisa. DAN: Sim? AUDIÊNCIA: [inaudível]? DAN: Sim, argv 0 inclui sempre o dot barra da chamada de função. Sim? AUDIÊNCIA: [inaudível]? DAN: Sim, cada um dos argumentos são terminou em caráter NULL porque são strings. AUDIÊNCIA: [inaudível]? DAN: Sim, argv argc é um ponteiro NULL. AUDIÊNCIA: [inaudível]? DAN: Oh yeah. Sim, desculpe. AUDIÊNCIA: Então, [inaudível]? DAN: Então a questão é se você tivesse o linha de comando dot cortar um ponto fora 1, 2, seria o número de linha de comando argumentos ser dois ou seria três? AUDIÊNCIA: Eu acho que isso não acontece realmente importa. Costumo dizer, oh, você não passou quaisquer argumentos de linha de comando quando, Obviamente, você chamou a função. Então, eu tendem a excluir vocalmente o função a partir da linha de comando argumentos, mesmo que seja incluídas na argv. DAN: Mas se fosse no test-- yeah-- e também se você disser algo argc como é igual a 3, você está em posição segura. Sim? AUDIÊNCIA: [inaudível]? DAN: Eu acho que, se em vez de chamar esse em argc e argv cordas suportes mas manteve os mesmos tipos e apenas chamado -lhes algo diferente, como um e b, será que ainda funciona? E ele continuaria a trabalhar, você só-- em vez de usar argc-- você pode usar a e b. Sim? AUDIÊNCIA: [inaudível]? DAN: Então a questão é GetString é indo para armazenar memória no heap porque GetString é char *. Ele armazena a memória na pilha porque chama-se agora dentro da malloc real implementação de GetString. OK, seguindo em frente. Segurança. Assim, para ser verdadeiramente seguro, você confia em nenhum uma e você não permitir o acesso a qualquer um de suas informações, razão pela qual todo mundo constrói suas próprias máquinas, seus próprios sistemas operacionais, todo o seu programas a partir do zero, e, obviamente, não ligar para qualquer outra máquina através da internet. Assim, os computadores são inseguros. Eles realmente são. Temos que confiar em outras pessoas. E a idéia de segurança é que você é tentativa de limitar a quantidade de confiança que você precisa. E um dos meios de fazer isso é por meio de criptografia. A criptografia é, essencialmente, temos segredos. Às vezes temos que passar nossos segredos Junto com, digamos, a internet ou outras coisas. E nós não queremos que as pessoas conhecer esses segredos. Então, nós transferimos nossos segredos para uma forma que esperamos que ninguém pode descobrir. Então, nós used-- através do curso deste class-- coisas como cifra de César e [Inaudível], que são muito, muito formas inseguras de criptografar as coisas. Eles são fáceis de descobrir o que eles são e quais são seus segredos são. O mundo real usa muito mais esquemas de criptografia complicados. E nós não vamos entrar em muito mais do que isso. Debugging. GDB é o melhor. Vou ressaltar novamente. Use GDB o tempo todo vez que você tem um problema. Os comandos que são úteis em GDB são quebrar, o que você quer passar uma linha número, um nome de função, essencialmente onde no seu código você quer parar, e ser capaz de assumir o controle. Imprimir leva uma variável e imprime seja lá o que é variável em que momento de sua execução. Em seguida move sua execução ao longo de uma única etapa. E passo passos dentro de uma função na sua execução. Outras coisas estão a correr, que é como você realmente executar seu código. Continue toma todas as medidas necessárias para chegar ao próximo ponto de parada. E há muitos, muitos outros. Procurá-los. Eles são ótimos. Sim? AUDIÊNCIA: [inaudível]? DAN: Sim, o que é um depurador. Assim, um depurador é um programa que permite depurar o programa. Não é um programa que encontra erros para Você, no entanto, que seria ótimo. E por último, para mim, é pesquisa. Assim, os tipos de pesquisa que falamos sobre nesta classe são a pesquisa linear, que é exatamente isso que você olhar através de cada elemento do espaço de busca, um elemento de cada vez, até encontrar o que você está procurando ou até atingir o final do seu espaço de busca em que apontar-lhe dizer que você não poderia encontrar o elemento que você estava procurando. E isto leva tempo a melhor constante, que é de 1 0 e, na pior linear tempo, que é de 0 n. Pesquisa binária, que precisa elementos sórdidos. Você vai para o meio dos seus elementos, ver se o elemento que você está procurando é maior ou menor do que o elemento que você está no meio. Ele é maior, você diz que o fundo de sua pesquisa o espaço é seu localização atual, o meio e reiniciar o processo. Se for menor, você parece dizer o-- que sim, o que foi? AUDIÊNCIA: [inaudível]? DAN: Sim. Qualquer tipo de espécie que tem sido ensinado em a classe é um jogo justo para o teste. [Risos] DAN: E o fato de você não ter tido para fazer isso por um conjunto de problemas, é justo jogo para o teste. AUDIÊNCIA: Podemos passar por isso como para-- DAN: Será ido mais. COLUNA 2: O código real para [Inaudível] é em study.cs50.net. Então, se você olhar para o problema prática na página merge sort de study.cs50.net, existe o código para a implementação de merge sort. Então você não tem que implementar it yourself esta noite. Mas certifique-se de compreendê-lo, em vez que apenas memorização. AUDIÊNCIA: [inaudível]? COLUNA 2: A página merge sort em study.cs50.net, não é uma prática problema que, se você clicar no problema, no final há uma solução, que é a fusão implementação de classificação. Mas certifique-se de compreendê-lo ao invés de apenas memorizá-la ou copiá-lo para baixo. AUDIÊNCIA: E um perfeitamente válido problema para o exame seria algo como aqui está uma lista. O que essa lista ficar depois um passo de seleções de tipo ou de tipo de inserção ou o que quer. Uma iteração completa da lista. Assim, mesmo se você não acabar precisando código para ele, você precisa entendê-lo o suficiente para saber como vai a ser modificar essa matriz. DAN: Isso é tudo para mim. [Aplausos] LUCAS: Olá a todos. Meu nome é Lucas. Eu vou falar sobre recursão, tudo os tipos que aprendemos, e um pouco de todos os ponteiros. Ok? Então, primeiro de tudo, a recursividade. O que significa dizer que uma função é recursiva? AUDIÊNCIA: Chama-se. LUCAS: OK, chama a si mesmo, sim. Assim como esta imagem, por exemplo. É como se a imagem dentro de uma imagem e assim por diante. Assim, por exemplo, você pode have-- como Dan que estava falando de busca binária. Uma maneira pela qual busca binária é recursiva é o fato de que você é tentando encontrar um número. Então você vai para o meio. E depois que você verifique se os números lá no lado esquerdo e no direito. E então se você descobrir o número é vai ser do lado esquerdo, que é o mesmo coisa como fazer a busca novamente, mas apenas no lado esquerdo da lista. Então é assim que soa como é recursiva. Então é por isso que vocês têm recursiva solução para merge sort. OK, então aqui está um exemplo. Então, digamos que eu quero escolher todos os números de 1 a n. Eu pode perceber que a soma de n número é n mais n menos 1 até 1. Mas então, se eu olhar para n menos 1 mais n menos 2 mais 1, que é a mesma coisa como números somando até n menos 1. Então eu posso dizer a soma de um montante igual n é igual a, mais a soma de n menos 1. Será que isso faz sentido? E eu também teria algo mais chamou o caso de base, que é a a soma dos números acima a zero seria zero. Então, assim que eu chegar ao número zero, eu parar de contar. Será que isso faz sentido? Então aqui está um exemplo de como Eu posso implementar isso. Então, eu tenho essa função em alguns. Isso leva um inteiro n. Então aqui eu primeiro verificar se n é inferior ou igual a zero. Então, se é menor ou igual a zero, I retornar zero, que é o nosso caso base. Caso contrário, eu só posso voltar n mais a soma dos números de um a n menos um. Faz sentido? Está bem. Então aqui está o que parece. Você tem soma de duas iguais 2 mais a soma de 1. E alguns de 1 é 1 mais o soma de 0, que é 0. Faz sentido? Então, se olharmos para a pilha de seu programa, este é o que parece. Primeiro, temos a função principal. E, em seguida, a função principal chamado soma 2. E, em seguida, soma dois vai dizer, oh, soma 2 é igual a 2, mais a soma de um. Então eu adicionar soma de 1 a pilha. E a soma de 1 vai chamar soma de 0, o que também vai ser adicionada para a pilha. E, em seguida, cada um destes são aqueles que em cima do outro tem que retornar antes que os outros podem continuar. Assim, por exemplo, aqui, soma de 0, em primeiro lugar, vai retornar 0. E em seguida, escolha quantia de 1. Em seguida, soma de 1 vai retornar 1 a soma de 2. E, finalmente, soma de dois vai para retornar 3 a principal. Será que isso faz sentido? É muito importante entender como a pilha está funcionando e tentar ver se faz sentido. OK, então a classificação. Então, por que é importante a classificação, em primeiro lugar? Por que devemos nos preocupar? Qualquer um? Dê-me um exemplo? Sim? AUDIÊNCIA: [inaudível]. LUCAS: Sim, OK. Então, você pode pesquisar de forma mais eficiente. Isso é um bom caminho. Assim, por exemplo, temos um monte de coisas, na verdade, em nossas vidas que são classificadas. Por exemplo, os dicionários. É muito importante ter todo o palavras algum tipo de ordem que pode acessar facilmente. Então, isso é o que ele estava dizendo. Você pode pesquisar de forma mais eficiente. Pense em quão difícil seria ter um dicionário em que as palavras estão em ordem aleatória. Você vai ter de se ver, muito bonito, cada palavra, até encontrar o palavra que você está procurando. Se você estiver usando o Facebook também, quando você está olhando para os seus amigos, você está vai ver que o Facebook colocar o seu amigo mais próximo é em cima das que você não fale muito. Se você percorrer todo o caminho até o fundo do sua lista de amigos, você vai ver pessoas que você provavelmente nem sequer lembre-se que você é amigos com. E isso é porque os tipos Facebook seus amigos com base em como você está perto deles. Assim, organizar os dados. Também Pokemon. Então você vê que todos os Pokemons têm números. E isso é como um fácil forma de acesso aos dados. AUDIÊNCIA: Acessando Pokemon. LUCAS: É. AUDIÊNCIA: [inaudível]. LUCAS: Yep. OK, então a seleção de classificação. Ordenar Seleção vai selecionar o menor valor indiferenciados de uma lista cada tempo em cada iteração. É uma espécie de como o tipo que você faz na sua cabeça quando você está tentando ordenar uma lista na mão. Basicamente, tudo que você faz é olhar para o número mais baixo. Você colocá-lo na lista de classificação. E então você olha para o próximo menor número. E então você continuar fazendo que e assim por diante. Assim, a seleção tipo é basicamente você selecionar cada vez menor valor indiferenciados. Colocar no final da classificados parte da lista. E continuar fazendo isso. Então, vamos ver rapidamente o que este parece. Então aqui está o classificado e lista de indiferenciados. Assim, para a ordenada de lista, é inicialmente vazio. E então eu estou indo para selecionar o menor número aqui, que é 2. Então eu recebo o número 2 e eu coloquei na parte da frente da lista. E então eu olho para a próxima menor elemento, o qual é de 3. Então, eu colocá-lo no final da lista ordenada. E então eu continuar fazendo isso. Acho 4 e colocá-lo no final. Encontre 5 e colocá-lo no final. E olha como todos aqueles momentos em que Eu estou dizendo que colocá-lo no final é, basicamente, trocar dois valores. Ok? E então o último, você só ter mais um elemento. Então, ele já está classificada. OK, então ordenação por inserção. Inclusão tipo que você vai ter também essa coisa de ter um ordenado e uma lista não ordenada. A única coisa é que toda vez que você está adicionando um elemento à classificadas lista, é só escolher o elemento que está na frente da lista de indiferenciados. E então você vai encontrar o que posição que deve ser classificada no parte da lista. Vamos ver o que isto é assim isso faz mais sentido. Assim, inicialmente, por exemplo, eu estou tentando para inserir o número três do parte classificada da lista. Assim, a lista não tem nada. Então, eu posso apenas colocar o número 3. Agora, eu quero adicionar o número 5 para a parte da lista ordenada. Então eu olhar para o número 5. Percebo que é maior do que 3. Então, eu sei que ele tem que ser depois de 3. Então eu coloquei 3 e 5. Então eu quero inserir o número 2. Percebo que o número 2 é, na verdade, durar, então o 3 eo 5. Então, eu realmente tenho que colocar tudo o maneira no início da lista. Então eu tenho que, tipo, mudar toda a elementos da lista ordenada para que eu possa abrir espaço para o número 2. Então eu vejo o número 6. Eu vejo que ele deve ser após 5. Então, eu colocá-lo lá. E, finalmente, eu olhar para o número 4. E notei que deveria situar-se entre 3 e 5. E então eu colocá-lo lá e mudança todos os outros elementos. Faz sentido? Bubble Sort. Então bubble sort é basicamente o que você está vai fazer-- chamamos isso de bolha tipo, porque você atravessa o lista-- é realmente melhor se eu apenas mostrar você gosta isso-- e você está indo para comparar números adjacentes. E você vai trocar a sua posições se eles não estão na ordem certa. Então, basicamente, o que vai acontecer é aqui, por exemplo, você tem 8 e 6. Você sabe que a ordem de classificação será realmente ser 6 e 5, certo? Então você vai para trocar as ordens. Então eu vejo 8 e 4 aqui. E eu faço a mesma coisa. Eu trocar novamente. E, finalmente, 2 e 8. Eu também trocá-los. É chamado Bubble Sort porque depois cada uma dessas iterações, na verdade, o maior número na lista fica tudo o caminho para o fim da lista. Será que isso faz sentido? Porque mantém troca-lo e movendo-o para a direita. OK, então esta é a segunda iteração. Isso seria a mesma coisa. Eu vou fazer um swap e em seguida, o último. Eu que não há trocas ea lista é ordenada. Assim, em Bubble Sort, nós basicamente manter atravessar a lista e trocar coisas até que eu perceber que eu não fiz quaisquer swaps fazendo a iteração, que significa que a lista já está classificado. Faz sentido? Vamos falar um pouco sobre o tempo de execução. Portanto, vocês lembram Big O, Omega, e Theta? Sim? OK, o que é Big O, em primeiro lugar? AUDIÊNCIA: [inaudível]. LUCAS: Sim, ele é chamado de pior caso tempo de execução, o que só significa que é o quanto você espera que o programa para tirar a correr. Como, em termos de-- neste caso-- n. O número de elementos na lista, no pior caso. Como, no pior caso possível. Assim, por Bubble Sort, por exemplo, temos Big O de n quadrado. Por que temos que? Porque é que Bubble Sort Big O n quadrado? AUDIÊNCIA: [inaudível]. LUCAS: Sim, então o pior caso será que eu vou ter que fazer n iterações. Assim, cada uma das iterações vai traga o maior elemento para a extremidade da lista. Então, o pior caso é que eu tenho para fazer aquela coisa n vezes. E para cada uma dessas vezes, eu tenho que fazer n swaps porque eu tenho que comparar cada um de dois elementos. Então é por isso que é n ao quadrado porque é n vezes n. Em seguida, a seleção espécie também é n quadrado porque, para cada iteração, eu tenho que olhar para cada elemento na lista. E depois encontrar o menor, o que significa que eu tenho que olhar através de n elementos. E eu tenho que fazer isso n vezes porque Eu tenho que selecionar todos os elementos n. Um tipo de inserção é também n quadrado porque o pior cenário será ser, um, eu tenho que inserir n números, certo? Então, eu já sei que eu vou ter n iterações. Mas para cada um desses números, se eu tivesse a olhar para todos os números em a lista ordenada e colocá-lo todo o caminho na parte dianteira, que vai ser n quadrada porque vai ser n vezes n novamente. Faz sentido? E sobre ômega? AUDIÊNCIA: [inaudível]. LUCAS: É o melhor cenário. Então, é como, em um monte de vezes para classificação, o melhor cenário é quando a lista já está classificado. Então, você realmente não tem para fazer qualquer coisa. Bubble Sort tem o melhor cenário de n. Vocês sabem por quê? AUDIÊNCIA: [inaudível]. LUCAS: Sim, se você manter o controle de se ração de dados teve quaisquer swaps ou não, se você tem algo como definido para verdadeiro se houver uma iteração, se o lista já está classificado, basicamente, o que vai acontecer é que eu vou tentar trocar a cada dois elementos adjacentes. Eu vou ver isso não há trocas. E eu só retornar imediatamente. Então, isso significa que eu tinha que percorrer a lista uma vez. Então é n porque eu olho a n elementos. Por seleção tipo n Square? Sim, mesmo que a lista é ordenada, para cada iteração da seleção tipo, eu tem que selecionar o elemento mínimo. Então isso significa que eu tenho que olhar para fora em todos os elementos do indiferenciados lista e encontrar o mínimo para cada iteração. Será que isso faz sentido? E a espada de inserção é n porque no caso que eu estou tentando inserir o números e todos os números, quando eu tentar inseri-los, eu vejo que eles estão na posição correcta. Eu não tenho que ir verificar todos os outros números na lista de indiferenciados. Então é por isso que vai ser n. Faz sentido? E o que é teta? AUDIÊNCIA: [inaudível]. LUCAS: O que, arrependido? Diga isso de novo. AUDIÊNCIA: [inaudível]. LUCAS: Exatamente. Assim você pode ver que apenas a seleção armazenado em merge sort tem tetas. E isso é porque você tem apenas theta se ambos Big O e Omega são os mesmos. Está bem. E, finalmente, merge sort é no registo n. E então, como Dan estava dizendo, merge sort é tipo como da mesma forma que você faz a busca binária. Então você começa a lista. E você vai cortar pela metade. E então você cortá-los em metades menores. E então você fundi-los. Vocês lembrar que, certo? OK, como ele dizia. OK, ponteiros. Então, o que é um ponteiro? AUDIÊNCIA: [inaudível]. LUCAS: Um endereço. Está bem. Eu sei que David mostra um grupo de vídeos de Binky e coisas que apontam entre si. Mas eu gosto de pensar ponteiros como apenas um endereço. Portanto, é uma variável que está acontecendo para armazenar um endereço. Então é só essa variável especial que é quatro bytes de comprimento. Lembre-se, esse ponteiro para qualquer coisa é sempre quatro bytes de comprimento para o nosso 32-bit máquina de modo que o caso com o aparelho. E ele só tem a localização de uma variável dentro do mesmo. OK, então não há essa memória, basicamente. Assim, cada bloco de memória, na verdade, tem um rótulo, o qual é o endereço do memória slotty. Então isso significa que eu posso ter um ponteiro que aponta para qualquer um desses endereços. Assim, a razão pela qual vamos usar ponteiros é se eu tenho que lembrar a localização que uma variável específica é uma memória. E vocês lembre-se que um dos casos foi se eu tiver uma função se eu tiver realmente quero que você swap para reais, eu realmente tem que enviar um ponteiro. Não é a variável. Vocês se lembra disso? O between-- diferença qual é o nome? Chamada pelo valor e chamando por referência, certo? OK, sim. Então chame por valor. Quando você acabou de enviar uma variável para funcionar você está apenas enviando um valor. Então, na verdade você está enviando uma cópia da variável. E o programa não poderia me importar menos sobre se a mesma variável, na verdade, faz uma cópia. E chamando por referência significa que Na verdade, estou enviando uma cópia do ponteiro para essa variável. Então, isso significa que eu estou enviando a localização dessa variável. Então, sinto que tenho a localização do variável, quando eu chamar a função com ponteiros, eu sou capaz de realmente alterar os dados que estavam no principal. Faz sentido? Embora, o ponteiro é uma cópia, a ponteiro ainda tem o endereço real de a variável que eu quero mudar. Faz sentido? Assim, a criação de ponteiros. Lembre-se, o ponteiro sempre do tipo que ele está apontando ao e, em seguida, uma estrela. E então você coloca o nome. Então lembre-se que sempre que você tem qualquer que seja estrela, é como um ponteiro para que qualquer que seja variável tipo que você tinha. Então, aqui em estrela, por exemplo, é um ponteiro e de um número inteiro. E depois de char estrela é um ponteiro estrela carvão animal e assim por diante. Sim? AUDIÊNCIA: E se temos uma ponteiro para n para estrelar x. Sei que cria um ponteiro para x. Será que ela também declarar x um número inteiro? LUCAS: OK, então quando você diz n estrela x, você não está criando um ponteiro para uma x variável. Você está criando um ponteiro chamado x. AUDIÊNCIA: [inaudível]. LUCAS: Então, quando eu digo n estrela x, eu sou dizendo, hey, na memória, eu vou conseguir uma dessas três caixas. E eu vou dizer que isso vai ser x, que é Vai ser um ponteiro. E uma coisa interessante sobre ponteiros é que nós dizemos que eles têm 4 bytes para uma máquina de 32-bit. E a razão para isso é porque 4 bytes são 32 bits. E máquinas que são de 64 bits, na verdade, têm endereços ponteiros que são de 64 bits. Por isso, apenas significa que a dimensão da endereços na máquina é diferente. Então Referenciando e Dereferencing. Existem dois operadores que Vocês devem se lembrar. O primeiro é comercial. A segunda é estrela. Não fique confuso com essa estrela e este estrela, porque lembre-se que, em Neste caso, você tem n estrela. É como uma coisa toda em conjunto. Não há espaço estrela n. Então, isso significa que ele é o tipo. Lembre-se, que quando você tem a estrela variável, você está falando sobre o tipo. Quando você tem apenas estrelas e, em seguida, o nome da variável, isto significa que você está dereferencing o ponteiro, que significa que você está olhando para o ponteiro, encontrar o endereço é apontando, indo para esse endereço, e olhando para sempre você tem lá. Então, eu digo aos meus alunos que quando você tem estrela, você deve pensar que é a abreviatura de conteúdo. Então se você tem um ponteiro e você fazer ponteiro estrela, é o o conteúdo do ponteiro. Então você vai para o que ele está apontando para e olhar para o conteúdo constante. E o comercial é o mesmo coisa como endereço. Então, se eu tenho uma variável a-- como, vamos dizer que eu fiz um int igual 3-- se eu quiser encontrar o endereço de que uma memória variável, eu só posso fazer comercial Uma. Por isso, é endereço de um. Faz sentido? Então, aqui está um exemplo. Isso está faltando int b e c int. Então int um é igual a 3 significa que Eu estou indo para ir para a memória. E eu vou encontrar um slot e colocar o número 3 aqui. E, em seguida, int b é igual a 4. Eu vou fazer a mesma coisa. Ir para a memória e colocar um número 4 em uma das caixas. E int é igual a 5. Encontre outra caixa e colocar um número 5. Então o que é esta linha está fazendo? n estrela pa igual a um comercial. Então, em primeiro lugar, n estrela aa. O que ele está fazendo? AUDIÊNCIA: [inaudível]. LUCAS: Sim, por isso n estrela pa, em primeiro lugar, declara um ponteiro chamado pa. E então ele está atribuindo o valor de ponteiro que pode ser o endereço de um. Então comercial Uma. Então, se eu fizer estrela pb, o que é uma estrela pb? Oh, desculpe. Isso também está em falta. n estrela pb. Quero dizer estrela pc. Eu sinto muito. É a mesma coisa. Mas agora eu sou bom ar criando um ponteiro para B e, em seguida, um ponteiro para c. Sim? AUDIÊNCIA: [inaudível]? LUCAS: Sim. Então, se você vai para a memória e você vai para a caixa que é designador para aa, você está realmente indo para veja o endereço de um. Ok? Sim? AUDIÊNCIA: [inaudível]? LUCAS: Sim, ponteiro é um endereço. Nunca se esqueça disso. É como o mais importante parte sobre ponteiros. Há armazenar e endereço a alguma variável. Algo mais? Alguma outra pergunta? Está bem. Então Ponteiros e matrizes. Lembre-se que quando eu faço int matriz 3, Basicamente, o que eu estou fazendo é que eu sou, tipo de, declarando em um ponteiro. Então matriz é tipo como um ponteiro para um lugar específico na memória em que eu alocados três slots para inteiros. Será que isso faz sentido? Então, quando eu faço int matriz 3, o que eu sou fazendo, basicamente, é a criação de três slots de memória. Então, eu só encontrar três slots de memória. Então, se eu fizer isso, então, um conjunto de estrelas, basicamente, o conteúdo do array, o que significa que eu apagar o ponteiro, eu vou para aquele lugar que ele está apontando para, e eu coloquei o número um. E depois, se eu fizer matriz estrela mais 1, isso é a mesma coisa que fazer matriz colchetes um, o que significa apenas que eu vá para o lugar que ela está apontando. E então a mais um marcas me deslocar uma posição. Então eu vou para essa posição, na verdade, e colocar o número dois. E então, finalmente, quando eu faço matriz mais dois, eu vou para onde apontador de matriz no. E então eu passo para os blocos de memória. E então eu coloquei o número três aqui. Sim? AUDIÊNCIA: array Assim estrela é simplesmente dizendo que o primeiro ponto. E você pode adicionar um, só porque estamos realmente só referenciar que primeiro endereço. LUCAS: É. Por que, por exemplo, dizer matriz 0, array 1 e matriz de 2? Eu estou dizendo, por que você faz 0, 1, 2, 3, em vez de 1, 2, 3? Uma das razões é, um, computador programadores preferem começar contando a partir de 0. Dois é porque quando você faz matriz 0, é a mesma coisa que fazer matriz plus 0, o que significa que eu vá para essa posição, e eu não ignorar quaisquer blocos de memória. Então eu não mover todos os blocos de memória. Sim? AUDIÊNCIA: [inaudível]? LUCAS: Então ela está perguntando o que é a diferença entre fazer este ou fazendo malloc. Uma das diferenças é que int matriz 3 é a criação de um matriz na pilha. E quando eu faço malloc, que cria na pilha. Será que isso faz sentido? Então como é que malloc realmente funciona? Então, por que ainda precisa usar malloc? Seu tipo de compilador descobre tudo as variáveis ​​que você declarou. E ele cria espaço para todos deles na pilha. Assim, todas as suas variáveis ​​vão estar em algum lugar na pilha. Então aqui está as variáveis ​​de ambiente. Então, basicamente, o espaço para as variáveis em memória é alocada em tempo de compilação. Então, isso significa que seu computador tem saber todas essas variáveis antemão. Ele não precisa saber qual o valor que você está indo para colocar neles. Mas é preciso saber como quantidade de memória que você precisa. Mas agora vamos dizer que, por exemplo, você está criando uma matriz ou tomar um string que você está tomando a partir do utilizador. Você não sabe quanto tempo a corda vai ser, por exemplo. Então você não sabe exatamente quantos blocos de memória que você alocar, certo? Por isso, não faz muito sentido para você quer dizer colocar 100 caracteres. E então o que se o usuário escreve 150? Você vai ser parafusado. Então, basicamente, você não pode ter certeza de como quantidade de memória que você precisa alocar quando você compilar o programa. Você só sabe que, em tempo de execução. É por isso que você tem a pilha. Assim, a pilha vai ter memória que você está alocando durante o duração do programa em execução. Então, basicamente, quando você faz malloc, o que você está fazendo é a alocação de memória em tempo de execução, o que significa que você está decidir naquele momento que você deve ter essa memória. Então é isso, quando você está atribuição. Será que isso faz sentido? Então lembre-se, a pilha tem variáveis que são criados em tempo de compilação. E então, o monte tem variáveis que são criados como você vai com malloc, por exemplo. AUDIÊNCIA: [inaudível]? LUCAS: Então é GetString vai chamar malloc. Deixe-me falar sobre malloc, e Vou explicar GetString. Então malloc é a mesma coisa como alocação de memória. Por isso, vai alocar memória no heap. E ele vai retornar um ponteiro para onde essa memória foi alocada no. Então, quando você fazer-- aqui para example-- n ponteiro estrela. E então ponteiro igual malloc tamanho de 10 polegadas vezes. Estou criando um ponteiro. E então eu estou atribuindo esse ponteiro para o valor do apontador que malloc está me dando. Então eu estou pedindo malloc você pode alocar espaço para 10 inteiros. Isso é o que ele está dizendo. E malloc me dá de volta a ponteiro para aquele lugar. Faz sentido? Está bem. Eu E GetString é, basicamente, fazer um chamar a malloc para que possa alocar memória durante a execução. Lembre-se sempre de verificar a nulidade porque malloc vai retornar nulo se não é possível alocar memória. Vamos dizer que você pedir um ridículo quantidade de memória. Seu computador não vai ser capaz de alocar muito. Então malloc é só ir para retornar null. Então lembre-se sempre de verificar se o ponteiro que você tem de malloc é nulo ou não, porque, se for, você pode ser referência um ponteiro e provocando falhas laterais. E, finalmente, não se esqueça sua memória livre. Malloc é a criação de memória no heap. E você tem que liberar a memória antes de o programa terminar. OK, isso é tudo para mim. Desculpe, Rob. Obrigado. [Aplausos] LUCAS: Todas as últimas perguntas antes de Rob vem? Não? Sim? AUDIÊNCIA: Eu não vi este online. Você carregou-o ainda? LUCAS: Eu acho que Dave é carregá-lo em breve. DAVE: Vai ser lançado. LUCAS: Ele vai ficar online. AUDIÊNCIA: É-se. LUCAS: É-se? Está bem. Sim? AUDIÊNCIA: [inaudível]? LUCAS: Sim, você deve liberar todo o memória que é colocado na pilha. AUDIÊNCIA: [inaudível]? LUCAS: Sim. Toda vez que você tem um malloc cultura, você deve ter uma cultura livre depois que você parar de usar essa variável. Então malloc e free são sempre juntos. Seus melhores amigos. Sim. Rob? ROB: Eu vou rapidamente. E também o vídeo será colocado. Eu tenho o microfone ligado. OK, então semana de cinco coisas. A primeira coisa que temos é a pilha. Então lembre-se que só há uma pilha quadro por chamada de função ativa. Vamos ver isso em um segundo. E também me lembro do que realmente se passa em cada quadro de pilha vão ser as variáveis ​​locais de nossas funções, os argumentos que são passados ​​para o nosso funções, juntamente com um par outras coisas que você realmente não precisa se preocupar. Então aqui está um exemplo de programa que, aviso, a principal é o retorno printfing valor de foo 4. foo só vai voltar a valor de bar 4 vírgula 6. E bar vai definir alguns locais n variável igual a 4 vezes 6. E em seguida, retornar n. Então, vamos olhar para a pilha todo a iteração atual do programa. Portanto, há o fundo da nossa stack. Lembre-se de que a pilha crescer. Assim, na parte inferior da nossa pilha, tem um quadro de pilha para o principal. Quando o programa começa, principal sempre vai estar no inferior da nossa pilha. E o que está dentro do nosso empilhar quadro para principal? Assim, mesmo que não existam locais variáveis ​​a principal, como eu disse antes, temos argc e rgv ocupando espaço dentro do quadro principal de pilha. Então principal agora vai chamando a função foo. E isso significa que foo vai obter o seu próprio quadro de pilha. Portanto, agora estamos dentro de a função foo. E o que precisa para ir em quadro de pilha do foo? Bem, foo tem um argumento n. E n é igual a 4, pois isso é o que principal é passar como argumento de foo. Então agora foo vai chamar bar. O que é bar vai ter dentro de seu 'quadro de pilha? Tem igual a 4 x y igual a seis. Isso não é tudo o que nós vamos ter no quadro de pilha porque bar tem também uma variável local n. E n vamos definir igual a 24. Então agora bar vai voltar n. Então bar está retornando 24 a o foo quadro de pilha. E porque é agora barra de retorno, que significa que estamos estourando o quadro de pilha para fora da barra da pilha. Assim, toda a memória que bar tinha sido usando é agora fora da pilha. Agora, foo também vai para retornar 24 a principal. Portanto, agora que foo está retornando, a memória foo que estava usando em sua ' quadro de pilha também está desaparecido. E agora, o principal vai chamar printf. Então printf é apenas uma outra função. Quando chamamos printf, que vai ser outro quadro de pilha para o printf chamada de função. O que estamos passando printf? Isso é o que está indo para ir em seu quadro de pilha. No mínimo, estamos passando que por cento i barra invertida n e o argumento 24. Poderia ter mais em sua estrutura de pilha se printf acontece a estar usando algum variáveis ​​locais. Nós não sabemos. Mas tudo o que acontece no printf do empilhar quadro. Vai executar o printf. Então printf é feito. Ele irá retornar. Finalmente, o principal está feito. Principal voltará. E então o nosso programa é feito. Sim? AUDIÊNCIA: Você está vendo [inaudível] argumentos [inaudível] parâmetros? ROB: Então há uma diferença sutil entre argumentos e parâmetros. E realmente, no falar comum, as pessoas tendem apenas para misturá-los o tempo todo. Mas parâmetros são os formais nome das coisas. Então argc e argv são o parâmetros para principal. Os argumentos são o que você realmente passar como esses parâmetros. Então lá quando eu chamar foo de 4, 4 é o argumento que eu estou passando. E o parâmetro n, dentro de foo, assume o valor 4 desde 4 foi o argumento. AUDIÊNCIA: [inaudível]? ROB: n é uma variável local para barrar. n ainda é local para foo, mas é um parâmetro para foo. Não é uma variável local. Sim? AUDIÊNCIA: [inaudível]? ROB: foo bar é apenas chamar e retornando Whatever Bar retornos. AUDIÊNCIA: [inaudível]? ROB: Sim, só para ver múltipla empilhar quadros. Sim? AUDIÊNCIA: Por foo foi chamado antes printf? ROB: Por que foo chamado antes printf? Então, eu poderia ter, em vez disso, fez algo como int x é igual a foo de 4 e, em seguida, impresso x. Mas em vez disso, eu combinei a função chamar o argumento de printf. Mas note que não podemos, na verdade, executar a chamada para printf até nós descobrir o que foo de 4 é. Então nós vamos avaliar isso. E só uma vez feito isso vai para voltar e avaliar isso. Sim? AUDIÊNCIA: Uma vez que tanto bar [inaudível] valor, por que não tem [inaudível]? ROB: Eles devem ser totalmente int. Isso não foi capturado mais vários passes. Assim deve ser int bar e int foo uma vez que ambos os estão retornando inteiros. Vazio é somente se eles não vão para retornar os valores reais. Sim? AUDIÊNCIA: Se você tivesse uma linha acima o retorno, [inaudível]? ROB: A linha de cima do retorno? AUDIÊNCIA: Yeah. Como se você fez printf e [inaudível], seria imprimir duas vezes? ROB: Então, dentro de foo? Se tivéssemos um printf aqui? AUDIÊNCIA: Yeah. ROB: Então, se nós tivéssemos um direito printf aqui, seria imprimir uma vez. Uma vez que estamos chamando foo uma vez direito aqui, então vamos acertar o printf. Então vamos chamá-bar. E então foo vai voltar. E é isso. Nós só encontrar sempre printf uma vez. Sim? AUDIÊNCIA: [inaudível] printf chamar foo porque estamos em primeiro lugar chamando printf e depois vamos passar os argumentos. ROB: Então, em teoria, não é printf chamar foo? Então, não. Apenas a fim de que c vai executar essas coisas é, antes que pudermos chamar uma função, todos os argumentos para a função precisa ser completamente avaliada. Então é isso completamente avaliado? Sim, ele é apenas um fio. É apenas um valor. Então nós temos que completamente avaliar isso. Uma vez feito isso, agora todos seus argumentos são avaliados. E agora nós podemos fazer a chamar para printf. Sim? AUDIÊNCIA: Uma pergunta. Se você tem uma função void, deve você tem retorno ponto e vírgula? ROB: Você não faz um ponto e vírgula retorno se você tem uma função void. Está bem. Então, agora algumas coisas heap. Então pilha é como vamos lidar com o gerenciamento de memória dinâmica. E isso contrasta diretamente com o pilha que poderíamos chamar de automático gerenciamento de memória. Então na pilha, você nunca tem para lidar com a forma como as variáveis ​​locais estão a ser empurrados e bateu fora tudo esses quadros de pilha e todas essas coisas. Você não tem que se preocupar com isso. É automático. Assim, a pilha é manual. E o [inaudível] vem destas funções malloc e free. Então aqui está um outro programa. Tudo o que estamos fazendo é mallocing um inteiro. Nós estamos armazenando-o em estrela x. Naturalmente, temos de verificar para ver se x é nulo. Então vamos apenas definir o que x está apontando para a 50. Imprima o que está apontando para x, print x, e depois livre x. Então, como é que isso realmente vai olhar se olharmos para a nossa pilha e pilha? Então, vamos começar de novo. A parte inferior da nossa pilha como antes. Lembre-se que te amontoar diretamente opõe-se a pilha de? Então, nós vamos ter o topo da nossa pilha lá em cima. Assim, o fundo da pilha a, temos nosso quadro de pilha para o principal. Ele tem o espaço para argc, argv, e nós Agora temos uma variável x local, que é uma estrela int. Então, vamos fazer uma iteração através deste programa. A primeira coisa que temos é uma chamada para malloc. Então, nós estamos fazendo uma chamada para malloc. Malloc é uma função. Vai chegar um quadro de pilha. O que estamos passando para malloc? Isso vai entrar do quadro de pilha. Estamos passando tamanho de n, que é 4. Então, que é passado para malloc. O que malloc fazer? Ele agarra-nos algum espaço no heap. Então, nós estamos indo para ir para a pilha. E nós vamos pegar 4 bytes da pilha. Então vamos dar esse um endereço arbitrários. 0x123 Basta fingir que é um endereço que está na pilha. Então, o que na verdade está dentro desse região de memória no endereço Ox123? Garbage. Então, nós não memorizou nada nele. Assim, tanto quanto sabemos, Poderia ser qualquer coisa. Você não deve assumir que é zero. É mais provável que não seja zero. Retornos Então agora malloc. E o que fazemos quando malloc retorna? Montamos o que ele retorna. Montamos x iguais ao que ele está retornando. Então o que é o retorno? Ele está retornando 0x123 vez que é a endereço do bloco de memória que apenas alocado no heap. Então retorne 0x123 x agora vai ser definido igual a 0x123 que, pictoricamente, nós freqüentemente desenhar como x tendo um real seta que aponta para esse bloco. Mas x é apenas armazenar esse endereço. Então, agora nós temos que verificar se x é nulo. Não é nulo. Fingimos que malloc que conseguiu. Então, agora estrela x é igual a 50. Assim estrela lembra que significa ir para esse endereço. Então 0x123 Vamos ir para esse endereço. Então, isso nos leva até lá. O que estamos fazendo nesse endereço? Nós estamos armazenando 50. Assim, após essa linha, que é o que as coisas estão indo para parecer. Então, agora ele não é mais lixo lá em cima. Agora sabemos que 50 é em que endereço particular porque nós configurá-lo para isso. Ok? Então agora vamos imprimir f. Então, primeiro vamos para imprimir estrela x. Então, qual é estrela x? Mais uma vez, a estrela x significa ir para a coisa que x está apontando. Então x é armazenar 0x123 Vá para isso. Ficamos com 50. Assim que imprimir f. E isso significa que ele vai imprimir 50. E depois que retorna. E depois temos o segundo printf. Agora estamos por cento p. Se você ainda não viu, essa é apenas como você imprimir um ponteiro. Portanto, temos por cento i, cento f, e todos aqueles já. Então por cento p, imprimir um ponteiro. Então x é um ponteiro. Então, se nós estamos indo para imprimir x si, estamos imprimindo o que na verdade está dentro x, o qual é 0x123 Assim, o primeiro print f vai imprimir 50. A segunda impressão f vai para imprimir 0x123 Sim? AUDIÊNCIA: Você usa por cento x para imprimir um apontador? ROB: Então você usa por cento x para imprimir um apontador? Então você pode, mas por cento x é justo, geral, pois, como se você tiver algum inteiro e que você deseja imprimir lo como um hexadecimal. Isso é apenas como você fazer isso. Considerando que, por cento d faria imprimir como decimal. É aí que nós começamos por cento d. i é apenas inteiro. por cento p é especificamente para ponteiros. Então x é um ponteiro. Queremos usar por cento p. Mas por cento x poderia trabalhar. Sim? AUDIÊNCIA: [inaudível]? ROB: Yeah. Pelo menos para este call-- então eu não inclui-lo aqui. Mas, estes dois argumentos são necessariamente dentro deste quadro de pilha juntamente com quaisquer variáveis ​​locais printf passa a ser utilizado. E, em seguida, a próxima chamada para printf agora dentro de printf quadro de pilha é por cento p barra invertida n e qualquer que seja o valor de x é, qual é 0x123. Sim? AUDIÊNCIA: [inaudível]? ROB: Ele vai imprimir algo que se parece com isso. AUDIÊNCIA: [inaudível]. ROB: Então ele imprime-lo em forma de endereço. Parece que um endereço. Sim? AUDIÊNCIA: [inaudível]? ROB: Por que é o quê? AUDIÊNCIA: [inaudível]? ROB: Porque é que este ponteiro 4 bytes? Portanto, há um monte de 0 em frente a este. Então, é realmente 0x0000000123. Em um sistema de 64 bits, não haveria um monte de mais zeros. Sim? AUDIÊNCIA: [inaudível]. ROB: Então o primeiro printf vai print-- AUDIÊNCIA: [inaudível]. ROB: Sim, está indo para imprimir que x está apontando. Estrela diz o que é isso coisa a apontar. Agarre-o. Então o que é que está apontando? 50. Agarre-o. Isso é o que vamos imprimir. Considerando que, o próximo, estamos apenas imprimir x si. O que está dentro de f? 0x123. Está bem. E então, finalmente, temos o livre. O que estamos passando para libertar? Estamos passando x. Naquela época, eu realmente exibido -lo no quadro de pilha. Então, nós estamos passando o valor 0x123 libertar. Então, agora livre sabe, tudo bem, Eu tenho que ir até a pilha e sem que a memória. Já não está usando o está no endereço 0x123. Tão livre vai lançar que a partir do heap. Agora a nossa pilha está vazia novamente. Não temos vazamentos de memória. Agora livre vai voltar. Observe que x ainda é 0x123. Mas isso agora não é válido memória. Não devemos mais desreferenciava x. Sim? AUDIÊNCIA: É retornar 0 redundante? ROB: É returen 0 redundante? Sim. Acabamos de colocar que lá porque temos um retorno de um para o ar. Então, é como, sim, permite incluem o retorno 0. Sim? AUDIÊNCIA: [inaudível]? ROB: Então, depois x livres, o que acontece se tentamos cancelar o ponteiro? É possível que nada dê errado. É possível que ainda vai receber 50. É possível, também, que essa memória é agora está sendo usado para outra coisa. Portanto, é um comportamento indefinido. E indefinida significa nada pode acontecer. Sim? AUDIÊNCIA: [inaudível]? ROB: Não, por isso, se você atribuir x para outra coisa. Então, se aqui dissemos x é igual a algo malloc else-- tamanho malloc event-- então que bloco original de memória não é liberada. E nós perdemos oficialmente. Isso é uma perda de memória. Perdemos todas as referências para esse bloco de memória. Então não há nenhuma maneira que nós podemos nunca libertá-la. OK, então, em seguida, retornar 0 significa feito. Todos estouro bem, então pilha. Qual é a ideia aqui? Então lembre-se, pilha está indo para baixo. Stack está subindo. Portanto, este foi o exemplo da palestra, Eu acho que, onde principal só vai chamar esta função foo, que vai a chamar-se de forma recursiva uma e mais uma vez. Então empilhar quadros vão funcionam exatamente da mesma. Então, vamos começar com principal como o quadro de pilha inferior. Então principal vai chamar foo, que está indo para obter um quadro de pilha. Então foo vai chamar foo novamente, o que vai ficar outro quadro de pilha. E então, de novo, e de novo, e de novo, e de novo, até que, eventualmente, corremos no heap. Então é assim que chegarmos um estouro de pilha. E, neste ponto, você SEG culpa. Ou você realmente seg falha antes neste ponto, mas sim. AUDIÊNCIA: É núcleo despejar o mesmo que culpa seg? ROB: Então você verá segmentação núcleo culpa despejado. Você ganha um dump de memória quando você SEG culpa. E é como uma reserva de todos os conteúdo da memória atual para que você pode tentar identificar por que o seg criticado. Sim? AUDIÊNCIA: [inaudível]? ROB: Então um meio falha de segmentação há um estouro de pilha. Então, não necessariamente. A falha de segmentação significa que você está memória tocar de um modo você não deve ser. Portanto, uma forma de isso acontecer é que, quando você estouro de pilha, começamos a tocar memória de uma forma que não deveria ser. Sim? AUDIÊNCIA: [inaudível]? ROB: Então, dentro de um loop infinito. Tipo, isso é como um infinito recursiva loop e então temos outro quadro de pilha de cada vez. Mas só dentro de um regular infinito enquanto um-- bem, não vamos nem imprimir F-- fazer alguma coisa. Qualquer que seja. Nós não vamos estar recebendo outro quadro de pilha. Nós apenas estamos indo para mantê-looping sobre esta única instrução. A pilha não está crescendo. É o fato de que cada recursiva chamada está nos dando um quadro de pilha. É por isso que temos um estouro de pilha. Sim? AUDIÊNCIA: Então, se você disse para obter o while e depois [inaudível]? ROB: Então, se dentro do loop while havia um printf, você ainda culpa não seg. Eu só não quero confundir as coisas. Seria circuito. Você deseja obter uma única pilha enquadrar para o printf. Então printf voltaria. Então você ciclo novamente. Você deseja obter uma única pilha enquadrar para o printf. Ele iria voltar. Quadro único pilha. Então você não está recebendo esse infinito empilhando pilha de quadros. AUDIÊNCIA: [inaudível]? ROB: Sim. Então esse estouro de pilha ocorre porque nenhum deles chamadas para foo estão voltando. Então, se voltarmos, então teríamos começar a perder quadros de pilha. E então nós não estouro de pilha. E é por isso que você precisa de um caso base para suas funções pessoais. Sim? AUDIÊNCIA: É o tamanho potencial ea pilha para a pilha o mesmo para todos os programas? ROB: Aproximadamente. É o tamanho do potencial da pilha e a pilha a mesma para todos os programas? Cerca. Há alguns randomização para em que a pilha e inicia onde a pilha começa. Se acontecer de você ter um monte de variáveis ​​globais e as coisas, que você pode tirar de algum espaço para o seu heap. Em um sistema de 64 bits, você praticamente tem memória infinita. Há tanta coisa. Entre 32 bits e 64 bits, que é uma diferença significativa. Você vai ficar muito mais pilha e heap space em um 64-bit sistema, pois não é apenas mais endereços que eles podem usar. Mas em um sistema individual, será ser mais ou menos a mesma quantidade de pilha e espaço de pilha. Tudo certo. Assim última coisa é a compilação. Então você deve saber este processo. Existem quatro grandes etapas. Assim, o primeiro deve-se ser fácil de lembrar. Pré-processamento. Ela tem o prefixo pré nele. Por isso, vem antes de tudo. A coisa a lembrar é o hash. Então haxixe define e haxixe inclui em tudo isso. Essas são todas pré-processador directivas. Estas são as coisas que os pré-processador cuida. Então, o que um pré-processador de fazer? É uma coisa realmente idiota. Tudo o que é capaz de são tudo isso cópia e Recortar e Colar operações. Assim, de hash inclui padrão i0 ponto h. O que é que está fazendo? Ele está agarrando o padrão i0 dot h arquivo e colá-lo para o topo onde quer que ele diz de hash inclui padrão dot h i0. E qualquer hash de definir que nós temos visto, o que é que está fazendo? Sua copiar o valor que o hash definido é definido como e colando que onde quer que você estiver usando o valor. Assim, o pré-processador só faz realmente operações baseadas em texto simples. Ele não faz nada inteligente. Então, tudo o resto é mais complicado. Portanto, agora que é pré-processador feito, nós realmente compilar. Então, o que a compilação significa? Estamos indo de código c ao código de montagem. Sim? AUDIÊNCIA: [inaudível]? ROB: Sim, nós pegamos isso. Então compilar. Estamos indo de C para montagem. Portanto, esta é uma mudança de linguagem real. Compilando-se significa ir de uma linguagem de alto nível para numa linguagem de nível inferior. E c é uma linguagem de alto nível em comparação com a montagem. O que é montagem? Suas instruções que são, muito muito, feito para o seu CPU. Mas o computador ainda não não entendo montagem. Ele só entende zeros e uns. Então, o próximo passo é a montagem, que nos leva a essas instruções que sua CPU compreende e realmente traduz-los, para os uns e zeros. Então C para montagem de binário. Mas eu não tenho um executável ainda. Então, acho que a biblioteca CS50. Nós fornecemos-lhe com um binário para esta biblioteca CS50, que tem GetString e GetInt e tudo isso. Mas o CS50 library-- e de itself-- não é executável. Ele não tem uma função principal. É apenas um monte de binário que você pode usar. Então ligação é assim que reunir todos desses arquivos binários diferentes em um arquivo executável real. Um que você pode digitar dot cortar um ponto fora. Então, isso é como o arquivo que você escreveu, - qualquer que seja o seu programa é-- Ceaser ponto c. Mas agora ele foi compilado até binário. Assim, o ponto de Ceaser. E esta é a nossa CS50 bibliotecas binário. E eles estão sendo combinadas num único executável. Sim? AUDIÊNCIA: [inaudível]? ROB: Então primeiro incluem, lembre-se, o hash incluir na verdade é um passo de pré-processador. Mas isso é separado. Se você não está usando todas as funções que estão fora do seu arquivo único, em seguida, Não, você não precisa de ligação nada pois você tem tudo. Dito isto, printf está sendo vinculado em. Se você nunca usar printf, isso é algo que tem de ser ligado em porque você não escreveu isso. E, de fato, printf é automaticamente ligada em. Você sabe como na linha de comando ou quando você digitar make, você vê que tem traço l CS50, que tem ligação na biblioteca CS50? Printf, e coisas assim, vai para ser ligado automaticamente. Qualquer outra dúvida sobre alguma coisa? AUDIÊNCIA: [inaudível]? ROB: Vinculação? Nós temos um monte de diferentes arquivos binários. Este é o exemplo canónica que usamos é a biblioteca CS50. Nós compilamos e dado a você o binária para esta biblioteca CS50. Você quer usar GetString em seu programa. Então, você vai usar GetString. Mas sem o meu código binário para GetString, quando você compilar o código para baixo, você não pode realmente executar o seu programa porque GetString String é ainda não totalmente definido. É só quando você ligar no meu binário que contém GetString que agora, tudo bem, eu posso realmente executar GetString. Meu arquivo está completo. E eu posso executar isso. Sim? AUDIÊNCIA: Faz ligando converter o binário para o executável? Assim, mesmo se você não tem outra bibliotecas, não seria ainda necessário para traduzir o [inaudível]? ROB: Então um executável ainda é em binário. É só combinar um todo bando de binários. AUDIÊNCIA: Muito obrigado. ROB: Não tem problema. Alguma outra pergunta? Caso contrário, está tudo pronto. Tudo certo. Obrigado. [Aplausos] AUDIÊNCIA: Obrigado. ROB: Yeah.