1 00:00:00,000 --> 00:00:00,499 2 00:00:00,499 --> 00:00:11,261 [MÚSICA DE JOGO] 3 00:00:11,261 --> 00:00:12,640 >> DAVID J. MALAN: Tudo bem. 4 00:00:12,640 --> 00:00:14,525 Este é CS50. 5 00:00:14,525 --> 00:00:16,009 E este é o início da semana 5. 6 00:00:16,009 --> 00:00:18,050 E como você deve ter notado, parte do material 7 00:00:18,050 --> 00:00:21,050 está ficando um pouco mais complexo, a pouco mais denso. 8 00:00:21,050 --> 00:00:24,560 >> E é muito fácil, especialmente se você foi o hábito há algum tempo, 9 00:00:24,560 --> 00:00:28,600 estar tentando rabiscar mais tudo o que fazemos, nós estamos dizendo na sala de aula. 10 00:00:28,600 --> 00:00:31,626 Mas perceber, que talvez não seja a abordagem pedagógica ideal 11 00:00:31,626 --> 00:00:34,250 para aprender esse tipo de material, e material de um modo mais geral. 12 00:00:34,250 --> 00:00:37,250 E assim temos o prazer de anunciar própria Gheng desse CS50 13 00:00:37,250 --> 00:00:39,780 Gong começou a se preparar um conjunto canônico de notas 14 00:00:39,780 --> 00:00:42,100 para o curso, a esperança da que é que, uma, estes 15 00:00:42,100 --> 00:00:44,030 não só servir como um referência e um recurso 16 00:00:44,030 --> 00:00:47,410 para material de revisão e vai de volta através do material que pode ter 17 00:00:47,410 --> 00:00:51,230 escapou-lhe a primeira vez, mas também para que suas cabeças podem ser mais 18 00:00:51,230 --> 00:00:53,740 -se que para baixo, quando chega a hora de palestra, 19 00:00:53,740 --> 00:00:56,960 de modo que você pode se envolver mais pensativo, como 20 00:00:56,960 --> 00:00:59,170 oposição ao mais scribbly. 21 00:00:59,170 --> 00:01:02,510 >> Com o que disse, o que você vai encontrar em o site é documentos como este. 22 00:01:02,510 --> 00:01:04,660 E observem, no canto superior esquerdo, há não apenas uma tabela de conteúdo, 23 00:01:04,660 --> 00:01:06,920 mas também códigos de tempo que será imediatamente saltar você 24 00:01:06,920 --> 00:01:09,077 para a parte apropriada no vídeo online. 25 00:01:09,077 --> 00:01:11,410 E o que Chang fez aqui é, essencialmente, documentado 26 00:01:11,410 --> 00:01:13,340 o que aconteceu neste especial de palestras. 27 00:01:13,340 --> 00:01:16,370 E muitas das palestras são Já estão online agora com este URL. 28 00:01:16,370 --> 00:01:20,110 E vamos continuar a postar o restante daqueles até o final desta semana, 29 00:01:20,110 --> 00:01:22,380 por isso tirar proveito desse recurso. 30 00:01:22,380 --> 00:01:25,740 >> Assim, sem mais delongas, começamos a descascar 31 00:01:25,740 --> 00:01:28,180 a camada que tem sido cadeia por algum tempo. 32 00:01:28,180 --> 00:01:30,670 E o que dizemos uma string na verdade é da semana passada? 33 00:01:30,670 --> 00:01:31,720 34 00:01:31,720 --> 00:01:32,900 Então, estrela de char. 35 00:01:32,900 --> 00:01:34,900 E Char estrela, bem, o que que isso realmente significa? 36 00:01:34,900 --> 00:01:37,150 Bem, todo esse tempo, se nós foi chamada de uma função, 37 00:01:37,150 --> 00:01:40,450 como getString, e armazenamento o retorno chamada 38 00:01:40,450 --> 00:01:42,910 valor de getString numa variable-- é chamado 39 00:01:42,910 --> 00:01:47,721 s tipo string-- que tenho escrito a linha de código lá em cima. 40 00:01:47,721 --> 00:01:49,970 E é só quando eu ver o meu caligrafia ampliada aqui 41 00:01:49,970 --> 00:01:51,930 eu perceber o quão atroz que é isso. 42 00:01:51,930 --> 00:01:54,180 >> No entanto, vamos supor que, no lado da mão direita 43 00:01:54,180 --> 00:01:57,070 é, no entanto, uma razoável representação do que é 44 00:01:57,070 --> 00:01:58,880 vem acontecendo tudo isso tempo com getString. 45 00:01:58,880 --> 00:02:00,380 getString, é claro, fica um string. 46 00:02:00,380 --> 00:02:01,691 Mas o que isso realmente significa? 47 00:02:01,691 --> 00:02:04,190 Isso significa que ele fica um pedaço de memória do sistema operacional 48 00:02:04,190 --> 00:02:06,040 chamando uma função, chamada malloc. 49 00:02:06,040 --> 00:02:07,390 Mas mais sobre isso mais tarde. 50 00:02:07,390 --> 00:02:09,139 E então ele preenche que pedaço de memória 51 00:02:09,139 --> 00:02:11,764 com as letras que o usuário tem digitei, seguido de, é claro, 52 00:02:11,764 --> 00:02:14,800 um caractere nulo, ou barra invertida zero no final. 53 00:02:14,800 --> 00:02:18,280 >> Enquanto isso, no lado esquerdo desta história, todo esse tempo, 54 00:02:18,280 --> 00:02:20,850 temos vindo a declarar uma variável, como s. 55 00:02:20,850 --> 00:02:24,770 E essa variável é o que agora vai começar a chamar um ponteiro. 56 00:02:24,770 --> 00:02:29,190 Não é uma caixa dentro da qual colocamos a corda, Daven, por si só, 57 00:02:29,190 --> 00:02:32,550 mas nós colocamos naquela praça caixa à esquerda o que exatamente? 58 00:02:32,550 --> 00:02:34,890 59 00:02:34,890 --> 00:02:35,390 Sim? 60 00:02:35,390 --> 00:02:37,118 >> AUDIÊNCIA: O endereço de onde ele está localizado na memória. 61 00:02:37,118 --> 00:02:38,118 >> DAVID J. MALAN: Exatamente. 62 00:02:38,118 --> 00:02:40,690 O endereço de onde Daven está localizado na memória. 63 00:02:40,690 --> 00:02:44,650 E não onde todos Daven está localizado, de per si, mas especificamente o endereço 64 00:02:44,650 --> 00:02:45,150 de quê? 65 00:02:45,150 --> 00:02:46,311 66 00:02:46,311 --> 00:02:46,810 Sim? 67 00:02:46,810 --> 00:02:47,460 >> AUDIÊNCIA: Primeiro personagem. 68 00:02:47,460 --> 00:02:50,209 >> DAVID J. MALAN: O primeiro caractere em Daven, que, neste caso, 69 00:02:50,209 --> 00:02:53,820 I proposto foi arbitrariamente e irrealisticamente 1, OX 1, 70 00:02:53,820 --> 00:02:55,910 o que significa apenas o número hexadecimal de 1. 71 00:02:55,910 --> 00:02:57,993 Mas provavelmente vai para ser um número muito maior 72 00:02:57,993 --> 00:03:01,260 que poderíamos chamar com um 0x como um prefixo, 73 00:03:01,260 --> 00:03:02,806 representando um personagem hexadecimal. 74 00:03:02,806 --> 00:03:05,930 E porque não precisamos de saber onde o resto dos personagens de Daven 75 00:03:05,930 --> 00:03:09,860 são, por causa do que design simples decisão que foi tomada há muitos anos? 76 00:03:09,860 --> 00:03:10,548 Sim? 77 00:03:10,548 --> 00:03:11,651 >> AUDIÊNCIA: Barra invertida 0. 78 00:03:11,651 --> 00:03:12,900 DAVID J. MALAN: Sim, exatamente. 79 00:03:12,900 --> 00:03:18,100 A barra invertida 0 permite-lhe, ainda que de tempo linear, para atravessar a corda, 80 00:03:18,100 --> 00:03:20,400 a pé da esquerda para a direita, com um loop, ou um tempo 81 00:03:20,400 --> 00:03:22,608 loop, ou algo parecido que, e determinar, oh, aqui 82 00:03:22,608 --> 00:03:24,751 é o fim dessa seqüência particular. 83 00:03:24,751 --> 00:03:27,000 Assim, com apenas o endereço em o início de uma string, 84 00:03:27,000 --> 00:03:30,290 podemos acessar a totalidade de , porque todo esse tempo, 85 00:03:30,290 --> 00:03:32,030 uma seqüência tem sido apenas uma estrela de char. 86 00:03:32,030 --> 00:03:36,370 >> Por isso, é certamente bem para continuar a utilizar a biblioteca CS50 e essa abstração, 87 00:03:36,370 --> 00:03:38,440 por assim dizer, mas vamos começar a ver exatamente 88 00:03:38,440 --> 00:03:41,230 o que está acontecendo debaixo de todo este tempo. 89 00:03:41,230 --> 00:03:45,260 Então você pode recordar este exemplo, também, a partir da última vez, comparar 0, 90 00:03:45,260 --> 00:03:47,300 que não chegou a comparar. 91 00:03:47,300 --> 00:03:49,070 Mas começamos a resolver isso. 92 00:03:49,070 --> 00:03:52,020 >> Mas como, talvez, uma reciclagem, Eu poderia interessar alguém 93 00:03:52,020 --> 00:03:54,261 em um elefante rosa de hoje, também feita por Chang? 94 00:03:54,261 --> 00:03:55,760 Que tal você na frente? [Inaudível]. 95 00:03:55,760 --> 00:03:56,660 Vamos lá para cima. 96 00:03:56,660 --> 00:03:58,740 >> E nesse meio tempo, como você venha, vamos 97 00:03:58,740 --> 00:04:01,670 considerar por um momento o que este código foi realmente fazendo. 98 00:04:01,670 --> 00:04:04,917 É declarar duas variáveis ​​se top, s e t, e chamando getString. 99 00:04:04,917 --> 00:04:08,250 Este não é um programa de fácil utilização, porque não lhe diz o que fazer. 100 00:04:08,250 --> 00:04:10,541 Mas vamos supor que estamos focando a parte suculenta. 101 00:04:10,541 --> 00:04:14,470 E então, o que fazemos, se s é igual a é igual a t, ele deve dizer printf, 102 00:04:14,470 --> 00:04:16,170 você digitou a mesma coisa. 103 00:04:16,170 --> 00:04:16,670 Olá. 104 00:04:16,670 --> 00:04:17,050 Qual o seu nome? 105 00:04:17,050 --> 00:04:17,779 >> JANELLE: Janelle. 106 00:04:17,779 --> 00:04:19,529 DAVID J. MALAN: Janelle, prazer em conhecê-lo. 107 00:04:19,529 --> 00:04:21,800 Portanto, o seu desafio no mão para este elefante 108 00:04:21,800 --> 00:04:25,230 é a primeira a chamar-nos um retrato do que está sendo representados naqueles dois primeiros 109 00:04:25,230 --> 00:04:25,970 linhas. 110 00:04:25,970 --> 00:04:28,139 Assim, s e t pode ser representado como na tela? 111 00:04:28,139 --> 00:04:30,680 E você pode apenas desenhá-lo com seu dedo na tela grande. 112 00:04:30,680 --> 00:04:31,780 113 00:04:31,780 --> 00:04:34,510 >> Portanto, há duas metades para cada lado da equação. 114 00:04:34,510 --> 00:04:37,760 Portanto, não há s à esquerda, e então GetString à direita. 115 00:04:37,760 --> 00:04:40,540 E depois há t do lado esquerdo, e, em seguida, GetString à direita. 116 00:04:40,540 --> 00:04:42,630 Então, como podemos começar fazer um desenho que 117 00:04:42,630 --> 00:04:46,340 representa o que está acontecendo aqui na memória, você diria? 118 00:04:46,340 --> 00:04:49,150 E deixe-me deixá-lo explicar o que você está fazendo que você vá. 119 00:04:49,150 --> 00:04:49,820 >> JANELLE: OK. 120 00:04:49,820 --> 00:04:58,890 Bem, em primeiro lugar, ele estaria pedindo você para obter a seqüência de entrada. 121 00:04:58,890 --> 00:05:00,439 E seria store-- oh, sinto muito. 122 00:05:00,439 --> 00:05:01,230 DAVID J. MALAN: OK. 123 00:05:01,230 --> 00:05:01,730 Boa. 124 00:05:01,730 --> 00:05:03,330 E isso é chamado de quê? 125 00:05:03,330 --> 00:05:03,950 Oh, OK. 126 00:05:03,950 --> 00:05:04,450 Continue. 127 00:05:04,450 --> 00:05:05,575 Eu não queria interromper. 128 00:05:05,575 --> 00:05:07,060 JANELLE: Desculpe. 129 00:05:07,060 --> 00:05:14,237 Por isso, seria introduzi-lo em o endereço não de-- certeza. 130 00:05:14,237 --> 00:05:17,320 Não me lembro exatamente o número, mas eu acredito que foi a partir de 0. 131 00:05:17,320 --> 00:05:18,420 >> DAVID J. MALAN: Está tudo bem, porque eu fiz os números acima, 132 00:05:18,420 --> 00:05:19,650 por isso não há resposta certa. 133 00:05:19,650 --> 00:05:22,105 >> JANELLE: Começando com a 0 arco. 134 00:05:22,105 --> 00:05:24,000 >> DAVID J. MALAN: OK, então o elemento 0. 135 00:05:24,000 --> 00:05:24,765 Claro. 136 00:05:24,765 --> 00:05:28,295 >> JANELLE: E então se foi como apenas um dois-letter-- 137 00:05:28,295 --> 00:05:30,496 >> DAVID J. MALAN: OK, de volta para você. 138 00:05:30,496 --> 00:05:33,629 >> JANELLE: Então o elemento 0, e em seguida, um elemento ou elemento 2. 139 00:05:33,629 --> 00:05:36,670 DAVID J. MALAN: E qual parte do a imagem que você está desenhando agora? 140 00:05:36,670 --> 00:05:37,690 A chamada para getString? 141 00:05:37,690 --> 00:05:38,830 Ou a declaração de s? 142 00:05:38,830 --> 00:05:42,890 >> JANELLE: A declaração de s, eu acredito. 143 00:05:42,890 --> 00:05:45,980 Oh, o getString, porque seria ser introduzido em cada um [? área. ?] 144 00:05:45,980 --> 00:05:46,510 >> DAVID J. MALAN: Good. 145 00:05:46,510 --> 00:05:47,051 Exatamente. 146 00:05:47,051 --> 00:05:49,300 Mesmo que isso efetivamente retorna um array, recall, 147 00:05:49,300 --> 00:05:53,300 quando voltarmos uma string, podemos índice para essa string usando 01 e 2. 148 00:05:53,300 --> 00:05:56,180 Tecnicamente, estes são, provavelmente, representado por endereços individuais, 149 00:05:56,180 --> 00:05:57,100 mas isso é bom. 150 00:05:57,100 --> 00:06:00,170 >> Então suponho que, se eu puder apenas rápido encaminhar para onde paramos 151 00:06:00,170 --> 00:06:04,320 última vez que, se um de as cordas era g a b e, 152 00:06:04,320 --> 00:06:10,337 barra invertida 0, representando assim Gabe entrada, como podemos representar s agora? 153 00:06:10,337 --> 00:06:12,670 Se esta é a memória que está foram devolvidos por getString? 154 00:06:12,670 --> 00:06:14,415 155 00:06:14,415 --> 00:06:17,610 >> JANELLE: Seria representado por um arco? 156 00:06:17,610 --> 00:06:18,750 >> DAVID J. MALAN: por um arco? 157 00:06:18,750 --> 00:06:19,130 Bem, não. 158 00:06:19,130 --> 00:06:21,171 Vamos apenas dizer que, pictoricamente, deixe-me ir em frente 159 00:06:21,171 --> 00:06:25,710 e propor que, se isso é s, esta é o valor de retorno de getString. 160 00:06:25,710 --> 00:06:29,482 E você desenhou isso como 0, 1, 2, que é perfeitamente razoável, porque nós 161 00:06:29,482 --> 00:06:30,940 pode indexar na seqüência, como tal. 162 00:06:30,940 --> 00:06:33,340 Mas apenas para ser consistente com última vez, deixe-me ir em frente 163 00:06:33,340 --> 00:06:37,310 e arbitrariamente propor que esta é o endereço 1, este é o endereço 2, 164 00:06:37,310 --> 00:06:39,597 este é o endereço 3, e assim por diante. 165 00:06:39,597 --> 00:06:41,430 E assim, apenas para ser super claro, o que está acontecendo 166 00:06:41,430 --> 00:06:44,580 ir no s como um resultado de que primeira linha de código, você diria? 167 00:06:44,580 --> 00:06:45,420 >> JANELLE: Endereço 1? 168 00:06:45,420 --> 00:06:46,420 >> DAVID J. MALAN: Exatamente. 169 00:06:46,420 --> 00:06:47,190 Assim, abordar 0x1. 170 00:06:47,190 --> 00:06:48,220 171 00:06:48,220 --> 00:06:51,230 E enquanto isso, deixe-me ir em frente e duplicar muito do que você fez 172 00:06:51,230 --> 00:06:52,740 e adicionar o meu próprio t aqui. 173 00:06:52,740 --> 00:06:56,340 Se eu fosse para digitar gabe de novo, uma segunda vez, 174 00:06:56,340 --> 00:07:01,530 quando solicitado com getString, onde, é claro, é gabe vai? 175 00:07:01,530 --> 00:07:02,280 Bem, presumably-- 176 00:07:02,280 --> 00:07:04,935 177 00:07:04,935 --> 00:07:05,975 >> JANELLE: Como aqui? 178 00:07:05,975 --> 00:07:06,850 DAVID J. MALAN: Yeah. 179 00:07:06,850 --> 00:07:08,516 JANELLE: Ou é também nas mesmas caixas? 180 00:07:08,516 --> 00:07:11,940 DAVID J. MALAN: Deixe-me propor, sim, exatamente, por isso, nessas caixas adicionais. 181 00:07:11,940 --> 00:07:15,230 Mas o que é fundamental, agora, é que, mesmo embora eu desenhei estas bem perto 182 00:07:15,230 --> 00:07:18,650 together-- 0x1, este é 0x2-- na realidade, 183 00:07:18,650 --> 00:07:25,750 isso agora pode ser o endereço 0x10, por exemplo, e de 0x11, 0x12 e, 184 00:07:25,750 --> 00:07:26,870 e assim por diante. 185 00:07:26,870 --> 00:07:29,955 E assim, se esse for o caso, o que vai acabar por aqui em t? 186 00:07:29,955 --> 00:07:30,830 >> JANELLE: 0x10? 187 00:07:30,830 --> 00:07:31,830 DAVID J. MALAN: Exatamente. 188 00:07:31,830 --> 00:07:33,180 Então 0x10. 189 00:07:33,180 --> 00:07:34,570 E agora, a pergunta final. 190 00:07:34,570 --> 00:07:37,510 Você tem, de longe, tinha que trabalhar a mais difícil para um elefante até o momento. 191 00:07:37,510 --> 00:07:42,650 Até agora, se eu puxar para cima o código mais uma vez, quando eu faço, na linha de três, 192 00:07:42,650 --> 00:07:47,630 se s é igual a igual t, o que eu sou, na verdade, comparando que temos desenhado aqui? 193 00:07:47,630 --> 00:07:49,271 >> JANELLE: Os dois endereços? 194 00:07:49,271 --> 00:07:50,270 DAVID J. MALAN: Exatamente. 195 00:07:50,270 --> 00:07:53,350 Então, eu estou dizendo é S igual igual at? 196 00:07:53,350 --> 00:07:56,210 Em outras palavras, é um igual igual a 10? 197 00:07:56,210 --> 00:07:59,710 E, evidentemente, o resposta óbvia é agora, não. 198 00:07:59,710 --> 00:08:02,920 E assim, este programa é, em última análise vai imprimir o quê, você diria? 199 00:08:02,920 --> 00:08:05,770 200 00:08:05,770 --> 00:08:08,405 >> JANELLE: Seria, você digitou a mesma coisa? 201 00:08:08,405 --> 00:08:11,446 >> DAVID J. MALAN: Então, se s representa 1 e t é 10? 202 00:08:11,446 --> 00:08:13,320 >> JANELLE: Escreveu coisas diferentes. 203 00:08:13,320 --> 00:08:13,570 >> DAVID J. MALAN: Exatamente. 204 00:08:13,570 --> 00:08:14,480 Você digitou coisas diferentes. 205 00:08:14,480 --> 00:08:14,850 Tudo certo. 206 00:08:14,850 --> 00:08:16,714 Então, uma salva de palmas, se pudéssemos, aqui. 207 00:08:16,714 --> 00:08:17,214 [Aplausos] 208 00:08:17,214 --> 00:08:17,708 Isso foi doloroso. 209 00:08:17,708 --> 00:08:18,208 Eu sei. 210 00:08:18,208 --> 00:08:19,684 Muito bem feito. 211 00:08:19,684 --> 00:08:24,690 Então agora vamos ver se não podemos desmembrar o que a correção era. 212 00:08:24,690 --> 00:08:28,040 E, claro, quando se fixa isso-- que agora vai representar em green-- 213 00:08:28,040 --> 00:08:29,690 fizemos algumas melhorias aqui. 214 00:08:29,690 --> 00:08:32,409 Em primeiro lugar, assim como uma sanidade verificar, estou verificando primeiro 215 00:08:32,409 --> 00:08:35,110 se s é igual a nulo e t é igual a null. 216 00:08:35,110 --> 00:08:39,440 E só para ficar claro, quando pode s ou t ser nulo no código como este? 217 00:08:39,440 --> 00:08:43,140 218 00:08:43,140 --> 00:08:44,490 Quando S ou T pode ser nulo. 219 00:08:44,490 --> 00:08:44,990 Sim? 220 00:08:44,990 --> 00:08:45,990 >> AUDIÊNCIA: [inaudível]. 221 00:08:45,990 --> 00:08:49,490 222 00:08:49,490 --> 00:08:50,510 >> DAVID J. MALAN: Exatamente. 223 00:08:50,510 --> 00:08:52,840 Se a seqüência de caracteres que o usuário digitado é um caminho muito longo 224 00:08:52,840 --> 00:08:56,140 para caber na memória, ou algum caso canto estranho assim, 225 00:08:56,140 --> 00:08:59,010 getString, como veremos, literalmente hoje, em sua documentação, 226 00:08:59,010 --> 00:09:02,330 diz que vai retornar nulo como um valor de sentinela especial, 227 00:09:02,330 --> 00:09:05,417 ou apenas uma espécie de símbolo especial isso significa que algo deu errado. 228 00:09:05,417 --> 00:09:07,500 Por isso, queremos verificar se há que, pois verifica-se 229 00:09:07,500 --> 00:09:09,720 que nulo é um valor muito perigoso. 230 00:09:09,720 --> 00:09:14,250 >> Muitas vezes, se você tentar fazer algo com nulo envolvendo um function-- passá-lo 231 00:09:14,250 --> 00:09:17,470 como entrada, para que a função instance-- pode muito vai bater e, com ele, 232 00:09:17,470 --> 00:09:19,090 derrubar todo o seu programa. 233 00:09:19,090 --> 00:09:22,570 Portanto, esta terceira linha agora é apenas uma sanidade cheque, verificação de erros, se você quiser. 234 00:09:22,570 --> 00:09:25,450 Isso é um bom hábito agora para nos para entrar em qualquer momento que 235 00:09:25,450 --> 00:09:28,050 tente usar um valor que poderia, potencialmente, ser nulo. 236 00:09:28,050 --> 00:09:32,000 >> Agora, na quarta linha aqui, "Se strcmp (s, t)," bem, 237 00:09:32,000 --> 00:09:33,180 o que é que se refere? 238 00:09:33,180 --> 00:09:36,750 Bem, disse que esta era uma forma muito sucinta função chamada para comparação de strings. 239 00:09:36,750 --> 00:09:40,370 E o seu propósito na vida é comparar seu primeiro argumento contra ela em segundo lugar, 240 00:09:40,370 --> 00:09:44,640 mas não em termos de seus endereços, como fizemos involuntariamente um momento 241 00:09:44,640 --> 00:09:48,270 atrás com o código vermelho, mas em vez de comparar os dois 242 00:09:48,270 --> 00:09:53,210 cordas no humanamente intuitiva forma, comparando este, contra este, 243 00:09:53,210 --> 00:09:56,690 contra isso, contra isso, e em seguida, parar se e quando um 244 00:09:56,690 --> 00:09:59,590 ou ambos os dedos atinge uma barra invertida 0. 245 00:09:59,590 --> 00:10:04,530 Strcmp Então anos atrás alguém implementado implementar para nós a funcionalidade 246 00:10:04,530 --> 00:10:08,890 que esperávamos, teríamos conseguido por apenas dois valores de comparação simples. 247 00:10:08,890 --> 00:10:14,929 >> Agora, francamente, eu continuo desenho todos estes vários números. 248 00:10:14,929 --> 00:10:17,470 Mas a realidade é, eu estive tornando-os para cima o tempo todo. 249 00:10:17,470 --> 00:10:19,580 E então deixe-me ir em frente e rabiscar estes para fora 250 00:10:19,580 --> 00:10:23,100 fazer um ponto em que, no final do dia e seguir em frente, 251 00:10:23,100 --> 00:10:30,160 nós não estamos indo realmente se preocupam com que aborda as coisas são, na verdade, 252 00:10:30,160 --> 00:10:30,790 na memória. 253 00:10:30,790 --> 00:10:34,320 Então eu não vou desenhar estes tipos de números muito mais, 254 00:10:34,320 --> 00:10:38,970 Eu sou apenas um resumo este fora um pouco mais amigável com apenas flechas. 255 00:10:38,970 --> 00:10:42,060 >> Em outras palavras, se s é um ponteiro, Bem, vamos apenas desenhá-lo, literalmente, 256 00:10:42,060 --> 00:10:45,430 como um ponteiro, uma seta apontando para de si mesmo para outra coisa, 257 00:10:45,430 --> 00:10:48,280 e não se preocupar muito mais sobre as minúcias desses endereços 258 00:10:48,280 --> 00:10:49,910 que, mais uma vez, eu fiz de qualquer maneira. 259 00:10:49,910 --> 00:10:52,680 Mas vamos ver os endereços, às vezes, quando a depuração do código. 260 00:10:52,680 --> 00:10:56,450 >> Agora, entretanto, este programa aqui correções, é claro, 261 00:10:56,450 --> 00:10:58,720 problema que comparando essas duas cordas. 262 00:10:58,720 --> 00:11:00,260 Mas nós funcionamos em outro problema. 263 00:11:00,260 --> 00:11:03,180 Esta foi a partir da cópia programar última vez, 264 00:11:03,180 --> 00:11:06,880 segundo o qual, eu estava tentando capitalizar apenas o primeiro caractere em uma string. 265 00:11:06,880 --> 00:11:09,620 Mas o que era o sintoma vimos da última vez, quando 266 00:11:09,620 --> 00:11:14,150 um usuário digitou um valor, como gabe em minúsculas, para s, 267 00:11:14,150 --> 00:11:19,310 então atribuído s em t, tal como na terceira linha não, 268 00:11:19,310 --> 00:11:22,900 e então eu tentei capitalizar t suporte 0? 269 00:11:22,900 --> 00:11:25,950 Qual foi o efeito de mudando t suporte 0 aqui? 270 00:11:25,950 --> 00:11:27,150 >> AUDIÊNCIA: Mudou s. 271 00:11:27,150 --> 00:11:29,360 >> DAVID J. MALAN: Sim, Mudei s, também. 272 00:11:29,360 --> 00:11:31,050 Porque o que realmente estava acontecendo? 273 00:11:31,050 --> 00:11:34,130 Bem, deixe-me ver se eu consigo limpar esta imagem, como se segue. 274 00:11:34,130 --> 00:11:41,390 >> Se s for, outra vez, a palavra g, A, B, E, barra invertida, 0 e s 275 00:11:41,390 --> 00:11:44,084 vamos continuar a desenhar como uma caixa aqui, mas não mais endereços. 276 00:11:44,084 --> 00:11:45,250 Vamos parar de fazer as coisas. 277 00:11:45,250 --> 00:11:47,510 Vamos apenas fazer um desenho para simplificar o mundo. 278 00:11:47,510 --> 00:11:52,640 >> Quando eu declaro t com corda t, que cria esse pedaço de memória. 279 00:11:52,640 --> 00:11:55,850 Praça passa a ser 32 bits na maioria dos computadores. 280 00:11:55,850 --> 00:11:59,530 Na verdade, se você já ouviu falar de um computador com uma arquitetura de 32 bits, 281 00:11:59,530 --> 00:12:03,000 muito chique-dizer, que apenas significa que ele usa endereços de 32 bits. 282 00:12:03,000 --> 00:12:05,370 E como um técnico de lado, Se você já se perguntou 283 00:12:05,370 --> 00:12:09,630 Por que os computadores mais antigos, se você realmente tentou sopa-los com muita memória RAM, 284 00:12:09,630 --> 00:12:12,360 apenas pode ter um máximo de quatro gigabytes de RAM, 285 00:12:12,360 --> 00:12:14,860 bem isso é porque, literalmente, computador antigo só podia 286 00:12:14,860 --> 00:12:17,250 Quantidade de tão elevada como 4 bilhões, 4 bilhões de bytes, 287 00:12:17,250 --> 00:12:20,590 porque se utilizando 32 bits números de endereços. 288 00:12:20,590 --> 00:12:23,260 >> Mas em qualquer caso, neste exemplo, da história muito mais simples. 289 00:12:23,260 --> 00:12:27,250 t é apenas um outro ponteiro, ou realmente uma estrela char, aka string. 290 00:12:27,250 --> 00:12:30,860 E como eu gostaria de atualizar esta imagem agora com essa segunda linha de código, 291 00:12:30,860 --> 00:12:31,950 após o ponto, ponto, ponto? 292 00:12:31,950 --> 00:12:35,845 Quando eu faço corda t é igual a s ponto e vírgula, como é que esta imagem mudar? 293 00:12:35,845 --> 00:12:37,500 294 00:12:37,500 --> 00:12:38,000 Sim? 295 00:12:38,000 --> 00:12:38,916 >> AUDIÊNCIA: [inaudível]. 296 00:12:38,916 --> 00:12:41,087 297 00:12:41,087 --> 00:12:42,020 >> DAVID J. MALAN: Yeah. 298 00:12:42,020 --> 00:12:42,600 Exatamente. 299 00:12:42,600 --> 00:12:45,620 Acabei de colocar uma flecha t caixa para o mesmo endereço, 300 00:12:45,620 --> 00:12:47,570 a mesma primeira letra deu. 301 00:12:47,570 --> 00:12:50,850 Ou tecnicamente, se esta cara ainda estava em 0x1, 302 00:12:50,850 --> 00:12:53,052 é como se eu tivesse Aqui 0x1 e 0x1 aqui. 303 00:12:53,052 --> 00:12:54,760 Mas, novamente, quem se importa sobre os endereços? 304 00:12:54,760 --> 00:12:56,345 É apenas a idéia de que agora importa. 305 00:12:56,345 --> 00:12:57,720 Então é isso que está acontecendo aqui. 306 00:12:57,720 --> 00:13:02,690 Então, é claro, se você fizer suporte t 0, que é a marcação de matriz, 307 00:13:02,690 --> 00:13:05,650 de course-- e, francamente, parece como se houvesse uma matriz por aqui, 308 00:13:05,650 --> 00:13:07,340 mas agora há uma coisa estranha. 309 00:13:07,340 --> 00:13:11,160 Saiba que a linguagem de programação, C, oferece esse recurso, 310 00:13:11,160 --> 00:13:14,650 pelo que, mesmo que t é um ponteiro, ou s é um ponteiro, 311 00:13:14,650 --> 00:13:18,050 você ainda pode usar aquele familiar, colchete confortável 312 00:13:18,050 --> 00:13:22,520 notação para ir para o primeiro elemento, ou o segundo elemento, ou qualquer elemento 313 00:13:22,520 --> 00:13:26,130 que esse ponteiro está apontando para porque, presumivelmente, ele 314 00:13:26,130 --> 00:13:29,410 é, como no caso presente, apontando para alguma matriz. 315 00:13:29,410 --> 00:13:30,340 >> Então, como vamos resolver isso? 316 00:13:30,340 --> 00:13:33,660 Francamente, isso é onde ele tem um pouco esmagadora à primeira vista. 317 00:13:33,660 --> 00:13:35,340 Mas aqui é uma versão nova e melhorada. 318 00:13:35,340 --> 00:13:37,460 >> Então, primeiro, eu estou ficando livrar da biblioteca CS50, 319 00:13:37,460 --> 00:13:41,170 apenas para expor que s é de facto uma estrela char, apenas um sinônimo. 320 00:13:41,170 --> 00:13:43,540 E t é também uma estrela de char. 321 00:13:43,540 --> 00:13:48,290 Mas o que está acontecendo no do lado direito da linha 322 00:13:48,290 --> 00:13:49,970 onde t é atribuído um valor? 323 00:13:49,970 --> 00:13:50,790 >> O que é malloc? 324 00:13:50,790 --> 00:13:51,630 O que é strlen? 325 00:13:51,630 --> 00:13:52,547 O que é sizeof (char)? 326 00:13:52,547 --> 00:13:54,380 Por que diabos faz isso olhar linha tão complexo? 327 00:13:54,380 --> 00:13:55,713 O que está fazendo em um nível elevado? 328 00:13:55,713 --> 00:13:56,482 329 00:13:56,482 --> 00:13:57,440 O que é que o armazenamento em t? 330 00:13:57,440 --> 00:13:58,646 Sim? 331 00:13:58,646 --> 00:14:01,104 AUDIÊNCIA: É a atribuição de uma certa quantidade de espaço de memória. 332 00:14:01,104 --> 00:14:03,032 É para guardar, eu acho, letras [inaudível]. 333 00:14:03,032 --> 00:14:04,032 >> DAVID J. MALAN: Perfeito. 334 00:14:04,032 --> 00:14:04,540 Perfeito. 335 00:14:04,540 --> 00:14:06,650 É atribuição de um certo quantidade de espaço de memória 336 00:14:06,650 --> 00:14:08,940 para armazenar, presumivelmente, cartas futuras. 337 00:14:08,940 --> 00:14:11,310 E, em particular, malloc portanto, está retornando de uma coisa? 338 00:14:11,310 --> 00:14:13,114 339 00:14:13,114 --> 00:14:14,851 >> AUDIÊNCIA: Retornando o [inaudível]? 340 00:14:14,851 --> 00:14:15,850 DAVID J. MALAN: Exatamente. 341 00:14:15,850 --> 00:14:18,850 Retornando o endereço de que a memória, que é uma maneira elegante de dizer, 342 00:14:18,850 --> 00:14:21,640 retorna o endereço do primeiro byte dessa memória. 343 00:14:21,640 --> 00:14:25,460 A responsabilidade recai sobre mim para lembrar a quantidade de memória que eu realmente 344 00:14:25,460 --> 00:14:27,140 alocado ou malloc pediu. 345 00:14:27,140 --> 00:14:28,384 >> Agora quanto é isso? 346 00:14:28,384 --> 00:14:30,550 Bem, mesmo que não haja um lote de parênteses aqui, 347 00:14:30,550 --> 00:14:32,970 malloc leva apenas um único argumento. 348 00:14:32,970 --> 00:14:37,250 E eu estou especificando strlen de s, para dar me como muitos bytes, como existem em s, 349 00:14:37,250 --> 00:14:37,800 mas adicione um. 350 00:14:37,800 --> 00:14:38,300 Por quê? 351 00:14:38,300 --> 00:14:39,030 352 00:14:39,030 --> 00:14:39,530 Sim? 353 00:14:39,530 --> 00:14:40,840 >> AUDIÊNCIA: A barra invertida 0. 354 00:14:40,840 --> 00:14:41,840 DAVID J. MALAN: Exatamente. 355 00:14:41,840 --> 00:14:43,423 Temos que fazer um pouco de limpeza. 356 00:14:43,423 --> 00:14:45,970 Então, porque não há uma barra invertida 0, é melhor se lembrar disso. 357 00:14:45,970 --> 00:14:47,310 Caso contrário, nós vamos para criar uma cadeia que 358 00:14:47,310 --> 00:14:49,170 não tem que terminador especial. 359 00:14:49,170 --> 00:14:52,640 >> Enquanto isso, apenas para ser super anal, tenho sizeof (char), 360 00:14:52,640 --> 00:14:55,730 apenas no caso de alguém corre o meu código não no aparelho CS50, 361 00:14:55,730 --> 00:14:58,220 mas talvez um computador diferente ao todo, onde chars 362 00:14:58,220 --> 00:15:01,470 é um byte, por convenção, mas dois bytes, ou algo maior do que isso. 363 00:15:01,470 --> 00:15:04,490 É apenas para ser super, Super aversão a erros. 364 00:15:04,490 --> 00:15:06,940 Mesmo que, na realidade, é provavelmente vai ser um 1. 365 00:15:06,940 --> 00:15:11,490 >> Agora, enquanto isso, eu vou em frente e copiar o corda, suporte t i é igual a faixa t s. 366 00:15:11,490 --> 00:15:14,962 E eu vou adiar para a última semana código-fonte para ver o que está acontecendo. 367 00:15:14,962 --> 00:15:17,670 Mas o principal argumento, eo razão de eu colocar o código agora em verde, 368 00:15:17,670 --> 00:15:22,520 é porque essa última linha, t suporte 0 é igual a toupper, 369 00:15:22,520 --> 00:15:25,230 tem o efeito de capitalizar que seqüência? 370 00:15:25,230 --> 00:15:26,960 t e / ou s? 371 00:15:26,960 --> 00:15:29,280 372 00:15:29,280 --> 00:15:30,580 Essa última linha de código. 373 00:15:30,580 --> 00:15:32,930 374 00:15:32,930 --> 00:15:35,560 >> Apenas t, porque o que é aconteceu desta vez, 375 00:15:35,560 --> 00:15:41,500 se eu ligeiramente desfazer o último passo, O que aconteceu é, quando eu chamo malloc, 376 00:15:41,500 --> 00:15:45,380 Eu essencialmente obter um pedaço de memória que é do mesmo tamanho que o inicial, 377 00:15:45,380 --> 00:15:47,020 porque essa é a aritmética que eu fiz. 378 00:15:47,020 --> 00:15:50,920 Eu estou armazenando em t endereço desse pedaço de memória. 379 00:15:50,920 --> 00:15:53,370 Mesmo que isso parece bom e bonito, agradável e em branco, 380 00:15:53,370 --> 00:15:56,882 A realidade é que é, o que vamos continuam chamando, os valores de lixo aqui. 381 00:15:56,882 --> 00:15:59,340 Esse pedaço de memória pode muito muito bem ter sido usado antes, 382 00:15:59,340 --> 00:16:00,940 alguns segundos, alguns minutos atrás. 383 00:16:00,940 --> 00:16:04,410 Portanto, não poderia absolutamente ser números ou letras lá, apenas por acaso. 384 00:16:04,410 --> 00:16:08,580 Mas eles não são válidos, até que eu me preencher este pedaço de memória 385 00:16:08,580 --> 00:16:12,510 com caracteres reais, como eu fazer nesse loop for lá. 386 00:16:12,510 --> 00:16:13,180 Tudo certo? 387 00:16:13,180 --> 00:16:16,180 >> Então, agora, o clímax da Estes três exemplos 388 00:16:16,180 --> 00:16:20,730 que foram aparentemente quebrado última vez, Neste exemplo swap, esta função 389 00:16:20,730 --> 00:16:23,670 trabalhou no sentido que trocou a e b. 390 00:16:23,670 --> 00:16:25,620 Mas não deu certo em que outro sentido? 391 00:16:25,620 --> 00:16:27,616 392 00:16:27,616 --> 00:16:28,614 Sim? 393 00:16:28,614 --> 00:16:29,612 >> AUDIÊNCIA: [inaudível]. 394 00:16:29,612 --> 00:16:35,600 395 00:16:35,600 --> 00:16:36,700 >> DAVID J. MALAN: Exatamente. 396 00:16:36,700 --> 00:16:39,530 Se eu fosse para chamar esta função de another-- por exemplo, 397 00:16:39,530 --> 00:16:42,870 a partir de uma função como principal, onde Eu tenho uma variável, x e y, como eu 398 00:16:42,870 --> 00:16:46,160 fez na semana passada, o mesmo código, e eu passar em x e y 399 00:16:46,160 --> 00:16:49,860 Trocar e depois chamar Swap-- isso, é claro, é a versão correta 400 00:16:49,860 --> 00:16:52,220 é o que estamos prestes a ver-- não funcionou. 401 00:16:52,220 --> 00:16:53,770 Então, qual é a correção? 402 00:16:53,770 --> 00:16:56,850 >> Bem, então, basta ser claro, deixe-me ir em frente 403 00:16:56,850 --> 00:17:05,450 e-- me dar um segundo aqui, e ver se eu posso mostrar-lhe a última, que 404 00:17:05,450 --> 00:17:12,464 será em-- vamos ver se eu posso encontrar esta OK fast-- real, [inaudível]. 405 00:17:12,464 --> 00:17:18,440 406 00:17:18,440 --> 00:17:19,240 OK, ele está lá. 407 00:17:19,240 --> 00:17:21,000 Assim, ignorar os comandos que eu estou apenas digitando. 408 00:17:21,000 --> 00:17:23,780 Eu quero que ele recuperar a o último minuto de um exemplo 409 00:17:23,780 --> 00:17:27,960 desde a última vez, que agora é chamado de não trocar. 410 00:17:27,960 --> 00:17:30,200 >> Portanto, não Swap é onde paramos da última vez, 411 00:17:30,200 --> 00:17:32,930 pelo qual, I inicializada x e y de um para dois. 412 00:17:32,930 --> 00:17:35,840 Eu, então, chamar de Swap, passando em 1 e 2. 413 00:17:35,840 --> 00:17:37,930 E então esta função trabalhou em algum sentido, 414 00:17:37,930 --> 00:17:40,750 mas não tinha permanente efeito de x e y. 415 00:17:40,750 --> 00:17:45,430 Então, a questão em apreço é, como agora é que vamos realmente resolver este problema? 416 00:17:45,430 --> 00:17:47,820 Qual é a solução na mão? 417 00:17:47,820 --> 00:17:53,150 >> Bem, em swap.c, que é novo hoje, notar algumas diferenças. 418 00:17:53,150 --> 00:17:54,700 x e y são o mesmo. 419 00:17:54,700 --> 00:17:57,250 Mas o que é claramente diferente sobre linha 25? 420 00:17:57,250 --> 00:17:58,880 421 00:17:58,880 --> 00:18:01,715 O que há de novo lá, se você se lembra o que parecia um segundo atrás? 422 00:18:01,715 --> 00:18:02,565 >> AUDIÊNCIA: [inaudível]. 423 00:18:02,565 --> 00:18:03,440 >> DAVID J. MALAN: Yeah. 424 00:18:03,440 --> 00:18:06,680 Assim, os ampersands são uma nova peça de sintaxe, não só neste programa, 425 00:18:06,680 --> 00:18:08,560 mas também em termos mais gerais em CS50. 426 00:18:08,560 --> 00:18:10,680 Até o momento, eu não acho que temos conhecimento de exemplos 427 00:18:10,680 --> 00:18:14,070 ou realmente falado sobre eles em qualquer detalhe, exceto, talvez, preventivamente 428 00:18:14,070 --> 00:18:16,467 em corte, um e comercial como este. 429 00:18:16,467 --> 00:18:19,300 Bem, acontece que é um comercial dos últimos pedaços de nova sintaxe 430 00:18:19,300 --> 00:18:20,174 vamos aprender. 431 00:18:20,174 --> 00:18:23,500 Tudo isto significa é o endereço de alguma variável. 432 00:18:23,500 --> 00:18:25,070 Em que endereço se x viver? 433 00:18:25,070 --> 00:18:26,510 Mas o endereço que y viver? 434 00:18:26,510 --> 00:18:28,700 Porque se o problema fundamental antes 435 00:18:28,700 --> 00:18:32,970 foi que x e y eram transferidos como cópias, o que nós realmente queremos fazer 436 00:18:32,970 --> 00:18:38,780 é fornecer Swap com como um tesouro mapa que leva a que x e y efectivamente 437 00:18:38,780 --> 00:18:41,910 estão na RAM, para que Trocar pode seguir esse mapa 438 00:18:41,910 --> 00:18:47,760 e ir para onde quer que x ou y marca o local e alterar os valores reais 1 e 2 439 00:18:47,760 --> 00:18:48,270 lá. 440 00:18:48,270 --> 00:18:50,710 >> Então trocar precisa mudar um pouco também. 441 00:18:50,710 --> 00:18:53,760 E, à primeira vista, isso pode parece um pouco semelhante ao carvão estrela. 442 00:18:53,760 --> 00:18:54,850 E de fato é. 443 00:18:54,850 --> 00:18:59,635 Assim, um é um ponteiro para o tipo de dados, com base nesta porção destacada? 444 00:18:59,635 --> 00:19:00,810 445 00:19:00,810 --> 00:19:01,620 Portanto, é um int. 446 00:19:01,620 --> 00:19:04,880 >> Assim, um não é mais um int, é o endereço de um int. 447 00:19:04,880 --> 00:19:07,910 E da mesma forma, b agora vai para ser o endereço de um int. 448 00:19:07,910 --> 00:19:12,470 Então, quando eu agora chamo de swap de Main, Eu não vou dar Trocar 1 e 2. 449 00:19:12,470 --> 00:19:15,540 Vou dar-lhe como Ox-algo e Ox-alguma coisa, 450 00:19:15,540 --> 00:19:19,820 dois endereços que levarão Trocar para seus locais reais 451 00:19:19,820 --> 00:19:21,310 na memória do meu computador. 452 00:19:21,310 --> 00:19:25,580 >> Então, agora, minha implementação restante precisa mudar um pouco. 453 00:19:25,580 --> 00:19:28,650 O que é, obviamente, diferente agora nestas três linhas de código? 454 00:19:28,650 --> 00:19:31,350 Há essas estrelas malditos todos sobre o lugar, certo? 455 00:19:31,350 --> 00:19:33,014 Então, o que está acontecendo aqui? 456 00:19:33,014 --> 00:19:33,514 Sim? 457 00:19:33,514 --> 00:19:35,055 >> AUDIÊNCIA: É, obviamente, [inaudível]. 458 00:19:35,055 --> 00:19:36,832 459 00:19:36,832 --> 00:19:37,990 >> DAVID J. MALAN: Exatamente. 460 00:19:37,990 --> 00:19:41,560 Portanto, neste context-- e isso não era a melhor decisão de projeto, na verdade, 461 00:19:41,560 --> 00:19:42,530 anos atrás. 462 00:19:42,530 --> 00:19:45,110 Neste contexto, em que você só tem uma estrela, 463 00:19:45,110 --> 00:19:48,240 e você não tem um tipo de dados, como int, imediatamente à esquerda, 464 00:19:48,240 --> 00:19:53,146 em vez disso você tem um sinal de igual, de forma clara, Neste contexto, quando você diz que estrelar um, 465 00:19:53,146 --> 00:19:56,980 isso significa ir para a endereço que está em um. 466 00:19:56,980 --> 00:19:58,870 Siga o mapa do tesouro, por assim dizer. 467 00:19:58,870 --> 00:20:01,720 >> E enquanto isso, na linha 37, isso significa a mesma coisa. 468 00:20:01,720 --> 00:20:05,460 Vá para o endereço de um, e colocar o que há? 469 00:20:05,460 --> 00:20:09,520 Seja qual for a local que b especifica. 470 00:20:09,520 --> 00:20:10,980 Em outras palavras, ir para b. 471 00:20:10,980 --> 00:20:12,130 Obter esse valor. 472 00:20:12,130 --> 00:20:15,620 Vá a uma e, por igual assinar, o operador de atribuição, 473 00:20:15,620 --> 00:20:17,010 colocar esse valor lá. 474 00:20:17,010 --> 00:20:19,272 >> Da mesma forma, int temperatura é apenas um int. 475 00:20:19,272 --> 00:20:20,730 Nada precisa mudar em Temp. 476 00:20:20,730 --> 00:20:24,810 É apenas um copo de reposição de Annenberg um pouco de leite ou suco de laranja. 477 00:20:24,810 --> 00:20:27,630 Mas eu preciso dizer, ir para b. 478 00:20:27,630 --> 00:20:31,449 Vá para esse destino e colocar o valor em temperatura lá. 479 00:20:31,449 --> 00:20:32,490 Então, o que está acontecendo, então? 480 00:20:32,490 --> 00:20:36,540 Quando eu realmente chamar Troque esse tempo, se esta primeira bandeja aqui representa principal, 481 00:20:36,540 --> 00:20:42,270 Nesta segunda bandeja representa swap, quando Eu passo Ampersand x e y comercial 482 00:20:42,270 --> 00:20:47,150 de principal de trocar, só para ficar claro, o que é esse quadro de pilha de recepção? 483 00:20:47,150 --> 00:20:48,700 484 00:20:48,700 --> 00:20:49,200 Sim? 485 00:20:49,200 --> 00:20:50,180 >> AUDIÊNCIA: [inaudível]. 486 00:20:50,180 --> 00:20:51,180 DAVID J. MALAN: Exatamente. 487 00:20:51,180 --> 00:20:53,129 O endereço de x e o endereço de Y. 488 00:20:53,129 --> 00:20:55,170 E você pode pensar neles como endereços postais. 489 00:20:55,170 --> 00:20:58,772 33 Oxford Street e 35 Oxford Street, e você 490 00:20:58,772 --> 00:21:01,230 deseja mover os dois edifícios que estão nessas localizações. 491 00:21:01,230 --> 00:21:04,680 >> É uma espécie de uma idéia ridícula, mas isso é tudo que queremos dizer por endereço. 492 00:21:04,680 --> 00:21:07,000 Onde no mundo pode você encontra esses dois inteiros? 493 00:21:07,000 --> 00:21:09,470 Onde no mundo você pode encontrar os dois edifícios? 494 00:21:09,470 --> 00:21:15,170 Então, se finalmente, depois de todo esse tempo eu entrar em código-fonte e compilar de hoje 495 00:21:15,170 --> 00:21:22,110 Trocar e correr ./swap, finalmente, para o primeira vez que nós realmente vemos que 496 00:21:22,110 --> 00:21:25,330 meus valores têm, na verdade foi trocado com sucesso. 497 00:21:25,330 --> 00:21:30,860 E agora, podemos até ter conhecimento do presente, digamos, gdb. 498 00:21:30,860 --> 00:21:32,740 >> Então deixe-me ir para o mesmo arquivo. 499 00:21:32,740 --> 00:21:35,010 Deixe-me ir em frente e correr gdb de ./swap. 500 00:21:35,010 --> 00:21:36,590 501 00:21:36,590 --> 00:21:40,547 E agora, em trocar, eu estou indo para ir em frente e definir um ponto de ruptura na principal. 502 00:21:40,547 --> 00:21:42,630 E agora eu estou indo para ir em frente e executar o programa. 503 00:21:42,630 --> 00:21:45,810 E agora vamos ver o meu código parou na linha. 504 00:21:45,810 --> 00:21:48,330 >> Se eu ir em frente e impressão x, o que devo ver aqui? 505 00:21:48,330 --> 00:21:49,314 506 00:21:49,314 --> 00:21:49,980 É uma pergunta. 507 00:21:49,980 --> 00:21:51,030 508 00:21:51,030 --> 00:21:51,530 Diga de novo? 509 00:21:51,530 --> 00:21:52,295 >> AUDIÊNCIA: [inaudível]. 510 00:21:52,295 --> 00:21:53,910 >> DAVID J. MALAN: Então números aleatórios, talvez. 511 00:21:53,910 --> 00:21:56,010 Talvez eu tenha sorte, e é agradável e simples, como 0. 512 00:21:56,010 --> 00:21:57,230 Mas talvez seja algum número aleatório. 513 00:21:57,230 --> 00:21:58,090 Neste caso, eu tive sorte. 514 00:21:58,090 --> 00:21:59,030 Ele só passa a ser 0. 515 00:21:59,030 --> 00:22:00,780 Mas é realmente sorte, porque não até que eu 516 00:22:00,780 --> 00:22:06,280 tipo seguinte e, em seguida, imprimir x tem que linha de código, linha 19, foram executados. 517 00:22:06,280 --> 00:22:10,942 >> Enquanto isso, se eu digitar próxima vez, e agora imprimir y, eu vou ver 2. 518 00:22:10,942 --> 00:22:13,900 Agora, se eu digitar em seguida, ele vai ficar um pouco confuso, porque agora, 519 00:22:13,900 --> 00:22:17,250 o printf vai aparecer a tela, como o fez. x é 1. 520 00:22:17,250 --> 00:22:18,606 >> Vamos fazer isso de novo. 521 00:22:18,606 --> 00:22:20,480 E agora, aqui é onde as coisas começam a ficar interessantes. 522 00:22:20,480 --> 00:22:21,580 523 00:22:21,580 --> 00:22:26,580 Antes de me chamar de Swap ou mesmo passo para ele, vamos dar uma olhadinha. 524 00:22:26,580 --> 00:22:28,980 x é, de novo, 1. 525 00:22:28,980 --> 00:22:33,240 Y é, é claro, sanidade rápido verificar, 2, por isso não é difícil lá. 526 00:22:33,240 --> 00:22:35,740 Mas o que é comercial x? 527 00:22:35,740 --> 00:22:36,760 528 00:22:36,760 --> 00:22:39,350 Resposta, é uma espécie de vista funky. 529 00:22:39,350 --> 00:22:43,500 Mas a estrela int em parênteses é apenas maneira de PIB de dizer isto é um endereço. 530 00:22:43,500 --> 00:22:48,290 Não é um int, que é um ponteiro para um int, ou de outro modo conhecido como um endereço. 531 00:22:48,290 --> 00:22:49,742 >> O que é essa coisa louca? 532 00:22:49,742 --> 00:22:51,825 Nunca vimos algo bem assim antes. 533 00:22:51,825 --> 00:22:53,650 534 00:22:53,650 --> 00:22:58,120 Portanto, este é o endereço no meu computador de memória de onde x acontece a viver. 535 00:22:58,120 --> 00:22:59,040 É Ox-alguma coisa. 536 00:22:59,040 --> 00:23:01,290 E este é, francamente, por que Eu comecei a desenhar setas, 537 00:23:01,290 --> 00:23:03,340 em vez de números, porque quem realmente se importa 538 00:23:03,340 --> 00:23:06,890 que é o seu int num determinado endereço que é assim tão grande. 539 00:23:06,890 --> 00:23:12,160 Mas bffff0c4, todos estes são na verdade dígitos hexadecimais, 540 00:23:12,160 --> 00:23:13,720 que vão de 0 a f. 541 00:23:13,720 --> 00:23:16,590 >> Então, nós não vamos morar muito tempo em que essas coisas são. 542 00:23:16,590 --> 00:23:19,400 Mas se eu imprimir y, é claro, eu vejo 2. 543 00:23:19,400 --> 00:23:22,440 Mas comercial y, vejo este endereço. 544 00:23:22,440 --> 00:23:26,527 E aviso, para os curiosos, Qual a distância entre x e y? 545 00:23:26,527 --> 00:23:27,985 Você pode ignorar a maior parte do endereço. 546 00:23:27,985 --> 00:23:29,330 547 00:23:29,330 --> 00:23:29,920 Quatro bytes. 548 00:23:29,920 --> 00:23:33,510 E isso é consistente com nossa anteriormente afirmam que o tamanho é um int? 549 00:23:33,510 --> 00:23:34,130 Quatro bytes. 550 00:23:34,130 --> 00:23:37,420 Portanto, parece que tudo está se alinhando bem, como você poderia esperar, na memória. 551 00:23:37,420 --> 00:23:40,010 >> Então, agora, vamos avançar rapidamente para o final desta história. 552 00:23:40,010 --> 00:23:43,290 Vamos em frente e digite passo, para mergulhar na Função Swap. 553 00:23:43,290 --> 00:23:46,880 Agora note, se eu digitar um, é idêntico ao endereço de x. 554 00:23:46,880 --> 00:23:52,130 Se eu digitar b, é idêntica para o endereço de y. 555 00:23:52,130 --> 00:23:57,020 Então, o que eu deveria ver se eu dizer, ir para o endereço de um? 556 00:23:57,020 --> 00:23:58,120 Assim imprimir estrelar um. 557 00:23:58,120 --> 00:24:00,130 Assim estrela significa ir lá, neste contexto. 558 00:24:00,130 --> 00:24:02,730 Ampersand significa que é o endereço. 559 00:24:02,730 --> 00:24:05,000 Assim, uma forma estrelar 1. 560 00:24:05,000 --> 00:24:09,590 E estrela de impressão b me dá 2. 561 00:24:09,590 --> 00:24:15,750 >> E deixe-me assumir, para o momento, que pelo menos o código que 562 00:24:15,750 --> 00:24:18,950 continuará a executar pode ser agora fundamentado por meio dessa forma. 563 00:24:18,950 --> 00:24:21,150 Mas vamos voltar a esta idéia em pouco tempo. 564 00:24:21,150 --> 00:24:23,850 Portanto, esta versão do swap é agora correcta e permite 565 00:24:23,850 --> 00:24:26,650 nos para trocar este tipo de dados particular. 566 00:24:26,650 --> 00:24:29,120 >> Assim, todas as perguntas, então em Trocar? 567 00:24:29,120 --> 00:24:29,890 Em estrela? 568 00:24:29,890 --> 00:24:30,690 No endereço? 569 00:24:30,690 --> 00:24:33,270 E você vai ver, com conjunto de problemas 4, de alguma forma, 570 00:24:33,270 --> 00:24:37,310 mas o problema ajuste 5, definitivamente, a forma como estes as coisas são úteis e obter muito mais 571 00:24:37,310 --> 00:24:39,584 confortável com eles, como um resultado. 572 00:24:39,584 --> 00:24:40,430 Qualquer coisa? 573 00:24:40,430 --> 00:24:40,930 Tudo certo. 574 00:24:40,930 --> 00:24:44,350 Então malloc é, novamente, esta função que apenas aloca memória, a memória 575 00:24:44,350 --> 00:24:45,330 alocação. 576 00:24:45,330 --> 00:24:47,024 E por que isso é útil? 577 00:24:47,024 --> 00:24:48,940 Bem, todo esse tempo, você estiver usando malloc. 578 00:24:48,940 --> 00:24:52,230 Se você considerar agora como GetString obras, presumivelmente, é 579 00:24:52,230 --> 00:24:56,140 foi pedir a alguém por um pedaço de memória, a qualquer momento o usuário digita uma string 580 00:24:56,140 --> 00:24:59,040 no, porque certamente não sabia, como pessoal CS50, 581 00:24:59,040 --> 00:25:02,710 como aquelas cordas grande que os seres humanos estão indo para escrever poderia ser. 582 00:25:02,710 --> 00:25:07,910 >> Então, vamos, pela primeira vez, começar a Descasque todas como funciona a biblioteca CS50, 583 00:25:07,910 --> 00:25:10,990 por meio de um par de exemplos que nos levará lá. 584 00:25:10,990 --> 00:25:15,300 Então, se eu abrir gedit e abrir scanf 0, 585 00:25:15,300 --> 00:25:17,055 vamos ver o seguinte código. 586 00:25:17,055 --> 00:25:18,720 587 00:25:18,720 --> 00:25:23,530 Scanf 0, disponível no site para hoje, tem relativamente poucas linhas de código 588 00:25:23,530 --> 00:25:25,351 aqui, 14 a 20. 589 00:25:25,351 --> 00:25:26,600 E vamos ver o que ele está fazendo. 590 00:25:26,600 --> 00:25:28,920 Ele declara um int, chamado x. 591 00:25:28,920 --> 00:25:30,850 Ele diz algo como, número por favor. 592 00:25:30,850 --> 00:25:33,940 E agora ele diz, scanf% i, e x. 593 00:25:33,940 --> 00:25:35,620 Portanto, há um monte de coisas novas lá. 594 00:25:35,620 --> 00:25:38,420 >> Mas scanf, você pode tipo de pensar como o oposto de printf. 595 00:25:38,420 --> 00:25:40,090 printf, é claro, para a impressão em tela. 596 00:25:40,090 --> 00:25:44,410 tipo scanf de scans do usuário do teclado algo que ele ou ela tenha digitado. 597 00:25:44,410 --> 00:25:46,550 >> % I é como printf. 598 00:25:46,550 --> 00:25:49,410 Isto significa que a espera usuário digite um int. 599 00:25:49,410 --> 00:25:52,820 E agora, por que você acha que eu pode estar passando scanf & x? 600 00:25:52,820 --> 00:25:54,030 601 00:25:54,030 --> 00:25:57,770 Se o objetivo de vida de scanf é fazer com que algo do usuário, 602 00:25:57,770 --> 00:26:02,480 qual é o significado de passando-o, & x, agora? 603 00:26:02,480 --> 00:26:02,980 Sim? 604 00:26:02,980 --> 00:26:03,896 >> AUDIÊNCIA: [inaudível]. 605 00:26:03,896 --> 00:26:05,540 606 00:26:05,540 --> 00:26:06,540 DAVID J. MALAN: Exatamente. 607 00:26:06,540 --> 00:26:12,900 Tudo o que eu, o ser humano, datilografar, minha entrada vai ser salvo no local. 608 00:26:12,900 --> 00:26:17,660 Não é suficiente, lembre-se, apenas passar em x, porque a gente já viu, 609 00:26:17,660 --> 00:26:21,630 qualquer momento que você passa apenas uma variável cru, como um inteiro, de alguma outra função, 610 00:26:21,630 --> 00:26:25,640 Claro, isso pode mudar isso variável, mas não permanentemente. 611 00:26:25,640 --> 00:26:27,360 Não pode ter um efeito sobre Principal. 612 00:26:27,360 --> 00:26:29,420 Ela só pode mudar sua própria cópia local. 613 00:26:29,420 --> 00:26:32,560 Mas se, em vez disso, você não dá-me a real int, 614 00:26:32,560 --> 00:26:36,640 mas você me dar instruções para int que, agora, sendo scanf, 615 00:26:36,640 --> 00:26:41,050 Certamente, eu posso seguir esse abordar e colocar um número não 616 00:26:41,050 --> 00:26:43,280 para que você tenha acesso a ele também. 617 00:26:43,280 --> 00:26:45,120 >> Então, quando eu executar este programa, vamos ver. 618 00:26:45,120 --> 00:26:49,660 Faça scanf 0 ponto barra, scanf 0. 619 00:26:49,660 --> 00:26:54,030 E se eu agora digite um número como 50, graças ao 50. 620 00:26:54,030 --> 00:26:58,150 Se eu agora digite um número como 1 negativo, para o negativo 1. 621 00:26:58,150 --> 00:27:04,200 Agora digite um número como 1,5, hm. 622 00:27:04,200 --> 00:27:06,030 Por que meu programa me ignorar? 623 00:27:06,030 --> 00:27:07,300 624 00:27:07,300 --> 00:27:09,880 Bem, porque simplesmente, eu te disse que esperar só um int. 625 00:27:09,880 --> 00:27:10,380 Tudo certo. 626 00:27:10,380 --> 00:27:11,630 Então essa é uma versão deste. 627 00:27:11,630 --> 00:27:16,600 Vamos levar as coisas acima de um entalhe e propor que isso não é bom. 628 00:27:16,600 --> 00:27:20,530 E aqui reside um exemplo muito simples de como podemos começar a escrever código 629 00:27:20,530 --> 00:27:24,450 que outras pessoas possam explorar ou comprometer, fazendo coisas ruins. 630 00:27:24,450 --> 00:27:28,336 Assim, linha 16, tão semelhantes em espírito de antes, 631 00:27:28,336 --> 00:27:29,960 mas eu não estou declarando-o int neste momento. 632 00:27:29,960 --> 00:27:32,970 Eu estou declarando-o caractere estrela, também conhecido como corda. 633 00:27:32,970 --> 00:27:35,190 >> Mas o que isso realmente significa? 634 00:27:35,190 --> 00:27:38,790 Então, se eu não especificar uma address-- e Eu estou chamando-o de forma arbitrária, buffer, 635 00:27:38,790 --> 00:27:43,370 mas eu poderia chamá-lo é, para ser simple-- e então eu faço isso, me explique, 636 00:27:43,370 --> 00:27:48,630 se você pudesse, com base na anterior lógica, o que está fazendo no scanf linha 18, 637 00:27:48,630 --> 00:27:55,000 se passe% s e buffer, qual é o endereço? 638 00:27:55,000 --> 00:27:58,210 O que é scanf, se você aplicar o exatamente a mesma lógica que a versão 0, 639 00:27:58,210 --> 00:28:00,640 vou tentar fazer aqui, quando o usuário digita algo em? 640 00:28:00,640 --> 00:28:02,630 641 00:28:02,630 --> 00:28:03,409 Sim? 642 00:28:03,409 --> 00:28:04,407 >> AUDIÊNCIA: [inaudível]. 643 00:28:04,407 --> 00:28:07,401 644 00:28:07,401 --> 00:28:08,890 >> DAVID J. MALAN: Exatamente. 645 00:28:08,890 --> 00:28:11,577 Scanf, pela lógica anterior, vai levar a string 646 00:28:11,577 --> 00:28:13,410 que o digitado humano em-- agora é uma string, 647 00:28:13,410 --> 00:28:15,790 não é um número, presumivelmente, se ele ou ela cooperates-- 648 00:28:15,790 --> 00:28:19,310 e vai tentar colocar isso seqüência na memória em qualquer endereço 649 00:28:19,310 --> 00:28:20,340 tampão especifica. 650 00:28:20,340 --> 00:28:23,870 E isso é ótimo, porque o buffer é realmente concebido para ser um endereço. 651 00:28:23,870 --> 00:28:30,470 >> Mas eu reivindico este programa é buggy em um forma muito grave, porque o valor é 652 00:28:30,470 --> 00:28:31,330 tampão por padrão? 653 00:28:31,330 --> 00:28:33,380 654 00:28:33,380 --> 00:28:34,790 O que eu inicializado em? 655 00:28:34,790 --> 00:28:35,770 O pedaço de memória? 656 00:28:35,770 --> 00:28:37,480 657 00:28:37,480 --> 00:28:38,620 Eu não tenho, certo? 658 00:28:38,620 --> 00:28:42,265 >> Então, mesmo que eu tenha atribuído um estrela de char que já não se chama s, 659 00:28:42,265 --> 00:28:48,030 é chamado em vez, de modo buffer-- vamos desenhar o nome da variável 660 00:28:48,030 --> 00:28:53,380 agora como buffer-- se eu não tenho chamado getString ou malloc aqui, 661 00:28:53,380 --> 00:28:56,030 que efetivamente significa que tampão é apenas um valor de lixo. 662 00:28:56,030 --> 00:28:57,030 >> Agora, o que isso significa? 663 00:28:57,030 --> 00:29:00,220 Isso significa que eu tenho dito scanf esperar uma string do usuário. 664 00:29:00,220 --> 00:29:01,300 E você sabe o quê? 665 00:29:01,300 --> 00:29:03,883 O que quer que essa coisa está apontando para-- e eu chamar ponto de interrogação, 666 00:29:03,883 --> 00:29:07,060 mas, na realidade, ele vai ser algo como OX 1, 2, 3, certo? 667 00:29:07,060 --> 00:29:10,730 É um valor falso que apenas passa a ser lá de antes. 668 00:29:10,730 --> 00:29:13,440 Então, dito de outra forma, é como se tampão é apenas 669 00:29:13,440 --> 00:29:16,180 apontando para algo na memória. 670 00:29:16,180 --> 00:29:17,610 Eu não tenho nenhuma idéia do que. 671 00:29:17,610 --> 00:29:24,130 >> Então, se eu digitar gabe agora, vai para tentar colocar g-a-b-e / 0 não. 672 00:29:24,130 --> 00:29:25,530 Mas quem sabe o que é isso? 673 00:29:25,530 --> 00:29:27,480 E, no passado, qualquer vez que tentei tocar 674 00:29:27,480 --> 00:29:29,770 memória que não pertence para nós, o que aconteceu? 675 00:29:29,770 --> 00:29:31,020 676 00:29:31,020 --> 00:29:32,870 Ou quase sempre. 677 00:29:32,870 --> 00:29:34,310 Falha de segmentação, certo? 678 00:29:34,310 --> 00:29:37,829 >> Esta seta, eu não tenho nenhuma idéia de onde ele é apontador. É só um valor aleatório. 679 00:29:37,829 --> 00:29:40,370 E, claro, se você interpretar um valor aleatório como endereço, 680 00:29:40,370 --> 00:29:42,610 você está indo para ir para algum destino aleatória. 681 00:29:42,610 --> 00:29:46,810 Então gabe pode de fato acidente meu programa, neste caso aqui. 682 00:29:46,810 --> 00:29:50,600 >> Então o que podemos fazer isso é quase tão ruim? 683 00:29:50,600 --> 00:29:52,660 Considere este terceiro e último exemplo de scanf. 684 00:29:52,660 --> 00:29:53,890 685 00:29:53,890 --> 00:29:56,870 Esta versão é melhor em que sentido? 686 00:29:56,870 --> 00:29:57,990 687 00:29:57,990 --> 00:30:01,400 Se você está confortável com o problema anterior, este é melhor. 688 00:30:01,400 --> 00:30:02,250 Por quê? 689 00:30:02,250 --> 00:30:03,250 >> AUDIÊNCIA: [inaudível]. 690 00:30:03,250 --> 00:30:06,235 691 00:30:06,235 --> 00:30:07,110 DAVID J. MALAN: Good. 692 00:30:07,110 --> 00:30:09,970 Então, neste caso, da linha 16 é melhor, no sentido 693 00:30:09,970 --> 00:30:12,030 que estamos explicitamente a atribuição de uma memória. 694 00:30:12,030 --> 00:30:14,190 Nós não estamos usando malloc, estamos usando a 2 semanas 695 00:30:14,190 --> 00:30:16,060 abordagem de apenas declarar uma matriz. 696 00:30:16,060 --> 00:30:18,130 E nós dissemos antes que uma seqüência é apenas um conjunto de caracteres, 697 00:30:18,130 --> 00:30:19,690 então isso é totalmente legítimo. 698 00:30:19,690 --> 00:30:22,910 Mas é, naturalmente, como você nota, tamanho fixo, 16. 699 00:30:22,910 --> 00:30:25,440 >> Portanto, este programa é totalmente seguro, se eu digitar 700 00:30:25,440 --> 00:30:29,760 em seqüências de um personagem, de dois caracteres cordas, 15 cadeias de caracteres. 701 00:30:29,760 --> 00:30:34,970 Mas assim que eu começar a digitar 16, 17, 18, 1000 cadeias de caracteres, 702 00:30:34,970 --> 00:30:37,390 onde está essa corda vai acabar? 703 00:30:37,390 --> 00:30:39,570 Vai acabar em parte aqui. 704 00:30:39,570 --> 00:30:42,820 Mas, então, quem sabe o que mais está além dos limites 705 00:30:42,820 --> 00:30:44,270 desta variedade particular? 706 00:30:44,270 --> 00:30:48,015 >> É como se eu tivesse declarou 16 caixas aqui. 707 00:30:48,015 --> 00:30:49,300 708 00:30:49,300 --> 00:30:52,690 Então ao invés de tirar todos os 16, vamos fingir que eu desenhei 16. 709 00:30:52,690 --> 00:30:56,540 Mas se eu tente ler uma string que é muito mais longo, como 50 caracteres, 710 00:30:56,540 --> 00:31:01,270 Eu vou começar a colocar a, b, c, d, x, y, z. 711 00:31:01,270 --> 00:31:04,916 E esta é presumivelmente algum outro segmento de memória 712 00:31:04,916 --> 00:31:06,790 que, de novo, pode causar meu programa trave, 713 00:31:06,790 --> 00:31:10,600 porque não pediu nada mais do que apenas 16 bytes. 714 00:31:10,600 --> 00:31:12,260 >> Então, quem se importa? 715 00:31:12,260 --> 00:31:13,880 Bem, aqui está a biblioteca CS50. 716 00:31:13,880 --> 00:31:17,220 E a maior parte deste é apenas como instruções em cima. 717 00:31:17,220 --> 00:31:21,670 A biblioteca CS50, todo esse tempo, teve esta linha na linha 52. 718 00:31:21,670 --> 00:31:23,680 Vimos typedef, ou você vai ver typedef 719 00:31:23,680 --> 00:31:27,930 em pset 4, que apenas cria uma sinônimo pelo qual caractere estrela pode ser mais 720 00:31:27,930 --> 00:31:29,290 simplesmente referido como string. 721 00:31:29,290 --> 00:31:31,540 Portanto, este é um dos algumas rodinhas 722 00:31:31,540 --> 00:31:34,120 nós usamos secretamente debaixo do capô. 723 00:31:34,120 --> 00:31:36,490 >> Enquanto isso, aqui está a função, getchar. 724 00:31:36,490 --> 00:31:38,190 Agora, aparentemente, não há corpo para ele. 725 00:31:38,190 --> 00:31:40,273 E, de fato, se eu continuar rolagem, eu realmente não 726 00:31:40,273 --> 00:31:42,080 ver qualquer implementações destas funções. 727 00:31:42,080 --> 00:31:43,140 728 00:31:43,140 --> 00:31:45,516 Como uma verificação de sanidade, por que isso? 729 00:31:45,516 --> 00:31:46,795 >> AUDIÊNCIA: [inaudível]. 730 00:31:46,795 --> 00:31:47,670 DAVID J. MALAN: Yeah. 731 00:31:47,670 --> 00:31:48,950 Portanto, este é o arquivo de cabeçalho. 732 00:31:48,950 --> 00:31:52,520 E arquivos de cabeçalho contêm protótipos, além de algumas outras coisas, ao que parece, 733 00:31:52,520 --> 00:31:53,780 como typedefs. 734 00:31:53,780 --> 00:31:56,910 Mas em CS50.c, que nós temos nunca lhe dado a título definitivo, 735 00:31:56,910 --> 00:32:02,100 mas foi no aparelho CS50 todos desta vez, bem no fundo de suas pastas, 736 00:32:02,100 --> 00:32:04,990 notar que não há um todo monte de funções aqui. 737 00:32:04,990 --> 00:32:06,720 >> Na verdade, vamos rolar para baixo. 738 00:32:06,720 --> 00:32:08,810 Vamos ignorar a maioria deles, por enquanto. 739 00:32:08,810 --> 00:32:12,670 Mas desça até getInt e ver como getInt funciona. 740 00:32:12,670 --> 00:32:13,890 Então aqui está getInt. 741 00:32:13,890 --> 00:32:17,727 E se você realmente se importa como chegar int funciona, aqui é a sua documentação. 742 00:32:17,727 --> 00:32:19,560 E entre as coisas ele diz é que lhe diz 743 00:32:19,560 --> 00:32:21,340 que as gamas de valores que pode retornar. 744 00:32:21,340 --> 00:32:24,400 É essencialmente negativo 2000000000 para o positivo 2 bilhões, mais ou menos. 745 00:32:24,400 --> 00:32:26,420 >> E ao que parece, tudo isso tempo, mesmo que nunca 746 00:32:26,420 --> 00:32:28,570 tinha que verificar para ele, Se algo der errado, 747 00:32:28,570 --> 00:32:30,680 verifica-se que todos os Neste momento, tem getInt 748 00:32:30,680 --> 00:32:33,600 foram retornando um especial constante, não nulo, 749 00:32:33,600 --> 00:32:36,760 mas sim INT_MAX, que é convenção apenas um programador. 750 00:32:36,760 --> 00:32:38,846 Isso significa que aqui é um valor especial. 751 00:32:38,846 --> 00:32:41,470 Certifique-se de verificar isso, basta no caso de algo correr mal. 752 00:32:41,470 --> 00:32:43,261 Mas nunca se preocupou com que até à data, 753 00:32:43,261 --> 00:32:45,200 porque mais uma vez, este destina-se a simplificar. 754 00:32:45,200 --> 00:32:46,950 >> Mas como é que se getInt implementado? 755 00:32:46,950 --> 00:32:48,450 Bem, um, ele não tem argumentos. 756 00:32:48,450 --> 00:32:49,390 Nós sabemos disso. 757 00:32:49,390 --> 00:32:50,820 Ele retorna um int. 758 00:32:50,820 --> 00:32:51,950 Nós sabemos disso. 759 00:32:51,950 --> 00:32:54,460 Então, como é que funciona debaixo do capô? 760 00:32:54,460 --> 00:32:58,290 >> Portanto, não há, aparentemente, um infinito ciclo, pelo menos o aparecimento de um. 761 00:32:58,290 --> 00:33:00,290 Observe que estamos usando getString. 762 00:33:00,290 --> 00:33:04,000 Então, isso é interessante. getInt chama a própria função, getString. 763 00:33:04,000 --> 00:33:05,645 E agora por que isso poderia ser o caso? 764 00:33:05,645 --> 00:33:07,400 765 00:33:07,400 --> 00:33:09,842 Por que estou sendo defensiva aqui na linha 165? 766 00:33:09,842 --> 00:33:11,390 767 00:33:11,390 --> 00:33:15,639 O que poderia acontecer em linha 164, só para ficar claro? 768 00:33:15,639 --> 00:33:16,930 É a mesma resposta de antes. 769 00:33:16,930 --> 00:33:18,660 770 00:33:18,660 --> 00:33:20,089 Pode ser apenas falta de memória. 771 00:33:20,089 --> 00:33:23,130 Algo vai mal com getString, temos de ser capazes de lidar com isso. 772 00:33:23,130 --> 00:33:27,070 E a razão de eu não retornam nulo é que, tecnicamente, null é um ponteiro. 773 00:33:27,070 --> 00:33:29,120 getInt tem que retornar um int. 774 00:33:29,120 --> 00:33:31,060 Então, eu tenho arbitrariamente decidiu, essencialmente, 775 00:33:31,060 --> 00:33:34,600 que 2 bilhões, mais ou menos, vai ser um valor especial que eu nunca pode 776 00:33:34,600 --> 00:33:35,970 realmente obter do usuário. 777 00:33:35,970 --> 00:33:39,930 É apenas o valor que eu vou para o lixo para representar um código de erro. 778 00:33:39,930 --> 00:33:41,540 >> Então, agora, as coisas ficam um pouco de fantasia. 779 00:33:41,540 --> 00:33:44,670 E não é bem a mesma função como antes, mas é muito similar. 780 00:33:44,670 --> 00:33:50,120 Então, observe, eu declaro aqui, na linha 172, tanto um int n e um char c. 781 00:33:50,120 --> 00:33:53,600 E então eu uso essa linha funky, sscanf, o que se vê 782 00:33:53,600 --> 00:33:55,990 não verifica uma string a partir do teclado. 783 00:33:55,990 --> 00:33:59,226 Ergue-se uma seqüência existente que o usuário já digitou. 784 00:33:59,226 --> 00:34:02,100 Então, eu já chamado getString, que significa que eu tenho uma string na memória. 785 00:34:02,100 --> 00:34:05,020 sscanf é o que você chamar uma função de análise. 786 00:34:05,020 --> 00:34:07,760 Ele olha para a cadeia eu tenho digitada, caractere por caractere, 787 00:34:07,760 --> 00:34:09,250 e faz alguma coisa útil. 788 00:34:09,250 --> 00:34:10,969 Essa seqüência é armazenado na fila. 789 00:34:10,969 --> 00:34:13,560 E eu sei que só indo voltar aqui e dizer, oh, OK, 790 00:34:13,560 --> 00:34:15,143 Liguei para ele não s neste momento, mas a linha. 791 00:34:15,143 --> 00:34:15,989 792 00:34:15,989 --> 00:34:18,080 >> E agora isso é um pouco diferente. 793 00:34:18,080 --> 00:34:22,480 Mas isso significa que de forma eficaz, por razões que de certa forma vai acenar as mãos no hoje, 794 00:34:22,480 --> 00:34:26,070 que estamos verificando a ver se o usuário digitou 795 00:34:26,070 --> 00:34:29,909 e int e talvez um outro personagem. 796 00:34:29,909 --> 00:34:33,610 Se o usuário digitou em um int, é vai ser armazenados em n, pois estou 797 00:34:33,610 --> 00:34:36,739 passando por este endereço, o novo truque que vimos hoje. 798 00:34:36,739 --> 00:34:41,570 Se o usuário também digitado em como 123x, que x 799 00:34:41,570 --> 00:34:45,060 vai acabar um carta em caráter c. 800 00:34:45,060 --> 00:34:48,739 >> Agora verifica-se que sscanf vai me dizer, de forma inteligente, 801 00:34:48,739 --> 00:34:54,750 quantas variáveis ​​foi sscanf com sucesso capaz de preencher. 802 00:34:54,750 --> 00:34:58,770 Então, por esta lógica, se a função Estou implementando é getInt, 803 00:34:58,770 --> 00:35:00,900 mas estou verificando, , potencialmente, para o utilizador 804 00:35:00,900 --> 00:35:04,190 ter digitado em um int seguido por outra coisa, 805 00:35:04,190 --> 00:35:08,580 o que eu quero de sscanf valor de retorno realmente ser? 806 00:35:08,580 --> 00:35:10,950 Se o objectivo é obter apenas um int do usuário? 807 00:35:10,950 --> 00:35:13,980 808 00:35:13,980 --> 00:35:19,300 >> Então, se sscanf retornos 2, o que significa isso? 809 00:35:19,300 --> 00:35:21,660 O usuário digitou algo como, literalmente, 810 00:35:21,660 --> 00:35:24,770 123x, o que é absurdo. 811 00:35:24,770 --> 00:35:27,490 É uma condição de erro, e Quero verificar para isso. 812 00:35:27,490 --> 00:35:32,960 >> Portanto, se o usuário digita isso em, pelo Nessa lógica, o que faz sscanf voltar, 813 00:35:32,960 --> 00:35:33,740 que você diria? 814 00:35:33,740 --> 00:35:35,070 815 00:35:35,070 --> 00:35:39,130 Então, ele vai retornar 2, porque o 123 vai entrar aqui, 816 00:35:39,130 --> 00:35:41,580 eo x vai acabar aqui. 817 00:35:41,580 --> 00:35:43,970 Mas eu não quero que o x para ficar cheio. 818 00:35:43,970 --> 00:35:48,580 Quero sscanf apenas ter sucesso em encher a primeira das suas variáveis. 819 00:35:48,580 --> 00:35:52,490 E é por isso que eu quer sscanf para retornar 1. 820 00:35:52,490 --> 00:35:55,750 >> E se isto é um pouco sobre a cabeça para o momento, isso é totalmente bom. 821 00:35:55,750 --> 00:36:00,030 Perceba, porém, que um dos valores de getInt e getString 822 00:36:00,030 --> 00:36:03,630 é que estamos fazendo um pedaço de um monte de verificação de erros como este para 823 00:36:03,630 --> 00:36:07,130 que, até agora, você pode muito bem digitar nada no teclado, 824 00:36:07,130 --> 00:36:08,490 e nós vamos pegá-lo. 825 00:36:08,490 --> 00:36:10,592 E certamente, o pessoal, não é definitivamente 826 00:36:10,592 --> 00:36:13,300 ser a fonte de um bug em seu programa, porque estamos na defensiva 827 00:36:13,300 --> 00:36:16,270 verificação de todos os estúpidos coisas que um usuário pode fazer, 828 00:36:16,270 --> 00:36:18,900 como digitar um texto, quando você realmente queria int. 829 00:36:18,900 --> 00:36:21,350 Assim, para agora-- nós viremos de volta a este antes long-- 830 00:36:21,350 --> 00:36:23,710 mas todo esse tempo, getString e getInt ter 831 00:36:23,710 --> 00:36:29,950 sido por baixo do capuz com esta ideia básica de endereços de memória. 832 00:36:29,950 --> 00:36:32,580 >> Então, agora, vamos tornar as coisas um pouco mais user-friendly. 833 00:36:32,580 --> 00:36:38,740 Como você pode recordar, a partir de Binky última tempo-- se meu mouse vai cooperate-- assim 834 00:36:38,740 --> 00:36:42,560 tivemos esse código, que francamente, é bastante absurda. 835 00:36:42,560 --> 00:36:45,330 Este código obtém nada útil, mas foi o exemplo 836 00:36:45,330 --> 00:36:48,330 que o professor Parlante utilizado para representar 837 00:36:48,330 --> 00:36:51,840 o que estava acontecendo em um programa envolvendo memória. 838 00:36:51,840 --> 00:36:54,850 >> Então, vamos recontar essa história de super brevemente. 839 00:36:54,850 --> 00:36:58,720 Estas duas primeiras linhas, em Inglês, fazer o quê, você diria? 840 00:36:58,720 --> 00:37:01,230 841 00:37:01,230 --> 00:37:05,430 Apenas no razoavelmente humano, mas ligeiramente termos técnicos, tomar uma facada. 842 00:37:05,430 --> 00:37:06,346 AUDIÊNCIA: [inaudível]. 843 00:37:06,346 --> 00:37:07,705 844 00:37:07,705 --> 00:37:11,080 >> DAVID J. MALAN: OK, você está estabelecendo endereços para o seu variáveis ​​x e y. 845 00:37:11,080 --> 00:37:15,520 Não é bem assim, pois x e y não são variáveis ​​no sentido tradicional. 846 00:37:15,520 --> 00:37:18,054 x e y são endereços ou vai armazenar o endereço. 847 00:37:18,054 --> 00:37:19,220 Então, vamos tentar mais uma vez. 848 00:37:19,220 --> 00:37:21,010 Não é um mau começo, no entanto. 849 00:37:21,010 --> 00:37:21,510 Sim? 850 00:37:21,510 --> 00:37:22,426 >> AUDIÊNCIA: [inaudível]. 851 00:37:22,426 --> 00:37:23,966 852 00:37:23,966 --> 00:37:24,840 DAVID J. MALAN: Good. 853 00:37:24,840 --> 00:37:26,173 Eu acho que é um pouco mais limpo. 854 00:37:26,173 --> 00:37:28,630 Declarando dois ponteiros, dois inteiros. 855 00:37:28,630 --> 00:37:30,150 E nós estamos chamando-x e y. 856 00:37:30,150 --> 00:37:32,790 Ou, se fosse desenhar isto como uma imagem de, novamente, 857 00:37:32,790 --> 00:37:36,410 lembro muito simplesmente que todos estamos fazendo com que a primeira linha 858 00:37:36,410 --> 00:37:39,690 está desenhando uma caixa como esta, com algum valor de lixo na mesma, 859 00:37:39,690 --> 00:37:41,920 e chamando-x, e depois outra caixa como esta, 860 00:37:41,920 --> 00:37:43,880 com um valor de lixo nele, chamando-y. 861 00:37:43,880 --> 00:37:45,810 Nós já declarou dois ponteiros que, em última instância 862 00:37:45,810 --> 00:37:47,860 irá armazenar o endereço de um int. 863 00:37:47,860 --> 00:37:49,170 Então, isso é tudo que existe. 864 00:37:49,170 --> 00:37:53,290 >> Então, quando Binky fez isso, o argila apenas olhou como este. 865 00:37:53,290 --> 00:37:55,350 E Nick apenas um tipo de embrulhado as setas, 866 00:37:55,350 --> 00:37:57,590 como se eles não estão apontando para qualquer lugar em particular, porque eles são apenas 867 00:37:57,590 --> 00:37:58,250 valores de lixo. 868 00:37:58,250 --> 00:38:01,670 Eles não estão explicitamente inicializado em qualquer em particular. 869 00:38:01,670 --> 00:38:03,980 >> Agora, a próxima linha de código, recall, era isso. 870 00:38:03,980 --> 00:38:07,510 Assim, em razoavelmente user-friendly, mas o Inglês um pouco técnico, 871 00:38:07,510 --> 00:38:09,790 o que é essa linha de código está fazendo? 872 00:38:09,790 --> 00:38:10,391 Sim? 873 00:38:10,391 --> 00:38:11,333 >> AUDIÊNCIA: [inaudível]. 874 00:38:11,333 --> 00:38:12,746 875 00:38:12,746 --> 00:38:13,950 >> DAVID J. MALAN: Perfeito. 876 00:38:13,950 --> 00:38:17,016 É atribuição da parcela do memória que é do tamanho de um int. 877 00:38:17,016 --> 00:38:18,140 E isso é metade da resposta. 878 00:38:18,140 --> 00:38:20,056 Você respondeu à direita metade da expressão. 879 00:38:20,056 --> 00:38:22,473 O que está acontecendo na lado esquerdo do sinal de igual? 880 00:38:22,473 --> 00:38:22,972 Sim? 881 00:38:22,972 --> 00:38:24,814 AUDIÊNCIA: e atribui à variável x? 882 00:38:24,814 --> 00:38:27,690 >> DAVID J. MALAN: e atribui à variável x. 883 00:38:27,690 --> 00:38:31,650 Então, para recapitular, aloca lado direito memória suficiente para armazenar um int. 884 00:38:31,650 --> 00:38:34,150 Mas malloc especificamente retorna o endereço 885 00:38:34,150 --> 00:38:37,270 desse pedaço de memória, o que você tem apenas proposto fica armazenado em x. 886 00:38:37,270 --> 00:38:42,560 >> Então, o que Nick fez da última vez com Binky é ele arrastou esse ponteiro para fora, o barro, 887 00:38:42,560 --> 00:38:46,820 para apontar agora em um pedaço branco de memória que é igual ao tamanho de um int. 888 00:38:46,820 --> 00:38:49,360 E, de fato, que significou para representar quatro bytes. 889 00:38:49,360 --> 00:38:55,310 >> Agora, a próxima linha de código fez isso, estrela x recebe 42. 890 00:38:55,310 --> 00:38:58,530 Então 42 é simples na lado direito, sentido da vida. 891 00:38:58,530 --> 00:39:00,500 Lado esquerdo, estrela x significa o quê? 892 00:39:00,500 --> 00:39:01,600 893 00:39:01,600 --> 00:39:03,280 Isso também pode ter gone-- está tudo OK. 894 00:39:03,280 --> 00:39:04,220 Está bem. 895 00:39:04,220 --> 00:39:06,875 >> AUDIÊNCIA: Basicamente, ir para o [inaudível] 896 00:39:06,875 --> 00:39:07,750 DAVID J. MALAN: Good. 897 00:39:07,750 --> 00:39:08,760 AUDIÊNCIA: [inaudível]. 898 00:39:08,760 --> 00:39:09,760 DAVID J. MALAN: Exatamente. 899 00:39:09,760 --> 00:39:11,979 Lado esquerdo significa ir para x. 900 00:39:11,979 --> 00:39:12,520 x é o endereço. 901 00:39:12,520 --> 00:39:15,520 É como 33 Oxford Street, ou OX 1. 902 00:39:15,520 --> 00:39:18,690 E estrela x significa ir àquela tratar e colocar o que há? 903 00:39:18,690 --> 00:39:19,520 42. 904 00:39:19,520 --> 00:39:21,290 >> Então, na verdade, isso é exatamente o que Nick fez. 905 00:39:21,290 --> 00:39:23,740 Ele começou com pelo, essencialmente, mentalmente 906 00:39:23,740 --> 00:39:26,270 apontando o dedo para x, seguindo a seta 907 00:39:26,270 --> 00:39:30,670 para a caixa branca do lado direito lado, e colocar o número 42 lá. 908 00:39:30,670 --> 00:39:34,120 Mas depois as coisas ficaram um pouco perigoso, certo? 909 00:39:34,120 --> 00:39:35,860 Binky está prestes a perder a cabeça. 910 00:39:35,860 --> 00:39:39,465 >> Estrela y é igual a 13, a má sorte, significa o quê? 911 00:39:39,465 --> 00:39:43,620 Então meios y estrela ir para o endereço em y. 912 00:39:43,620 --> 00:39:45,630 Mas qual é o endereço em y? 913 00:39:45,630 --> 00:39:47,899 914 00:39:47,899 --> 00:39:49,440 Tudo bem, é valor de lixo, certo? 915 00:39:49,440 --> 00:39:50,800 Eu tirei-o como um ponto de interrogação. 916 00:39:50,800 --> 00:39:54,850 Nick chamou-o como uma seta enrolado. 917 00:39:54,850 --> 00:39:59,600 E assim que você tenta fazer estrela y, dizendo ir lá, 918 00:39:59,600 --> 00:40:03,872 mas não há uma legítimo endereço, é uma localização falsa, 919 00:40:03,872 --> 00:40:05,080 o programa vai falhar. 920 00:40:05,080 --> 00:40:08,580 E a cabeça de Binky vai para voar aqui, como o fez. 921 00:40:08,580 --> 00:40:12,130 >> Então, no final, este programa era apenas plana falha fora. 922 00:40:12,130 --> 00:40:13,540 Era um programa de buggy. 923 00:40:13,540 --> 00:40:14,760 E precisava ser corrigido. 924 00:40:14,760 --> 00:40:18,260 E a única maneira, realmente, para corrigi-lo seria, por exemplo, esta linha de, 925 00:40:18,260 --> 00:40:21,010 que nem sequer chegar, porque o programa caiu muito em breve. 926 00:40:21,010 --> 00:40:26,170 Mas se tivéssemos de corrigir isso, o que efeito que fazer y iguais x tem? 927 00:40:26,170 --> 00:40:30,010 Bem, essencialmente aponta y em qualquer valor x está apontando. 928 00:40:30,010 --> 00:40:32,430 >> Assim, na história de Nick, ou a história de Binky, tanto 929 00:40:32,430 --> 00:40:34,640 x e y foram apontando para o pedaço branco de memória, 930 00:40:34,640 --> 00:40:38,300 de modo que, finalmente, quando não estrelar y é igual a 13, mais uma vez, 931 00:40:38,300 --> 00:40:43,080 você acaba colocando 13 em o local apropriado. 932 00:40:43,080 --> 00:40:47,640 Assim, todas estas linhas são perfeitamente legítima, com exceção de um presente, 933 00:40:47,640 --> 00:40:51,730 quando isso aconteceu antes de você efectivamente atribuídos y algum valor. 934 00:40:51,730 --> 00:40:54,290 >> Agora, felizmente, você não tem que raciocinar através de todos 935 00:40:54,290 --> 00:40:56,560 desses tipos de problemas em seu próprio país. 936 00:40:56,560 --> 00:40:59,310 Deixe-me ir em frente e abrir uma janela de terminal aqui 937 00:40:59,310 --> 00:41:03,050 e abrir-se, por um momento, um super programa curto que 938 00:41:03,050 --> 00:41:04,360 também é uma espécie de inútil. 939 00:41:04,360 --> 00:41:05,152 É feio. 940 00:41:05,152 --> 00:41:06,610 Não conseguir qualquer coisa útil. 941 00:41:06,610 --> 00:41:10,180 Mas isso não demonstrar problemas de memória, por isso vamos dar uma olhada. 942 00:41:10,180 --> 00:41:11,830 >> Principal, super simples. 943 00:41:11,830 --> 00:41:14,830 Aparentemente, chama uma função, f, e, em seguida, retorna 0. 944 00:41:14,830 --> 00:41:16,310 É meio difícil de estragar isso. 945 00:41:16,310 --> 00:41:18,540 Então principal é muito bom, até agora. 946 00:41:18,540 --> 00:41:20,100 >> Assim, f é problemático. 947 00:41:20,100 --> 00:41:22,120 E só não colocar muito esforço em nomeá-lo 948 00:41:22,120 --> 00:41:23,990 aqui, para manter o foco sobre o código. 949 00:41:23,990 --> 00:41:25,740 f tem duas linhas. 950 00:41:25,740 --> 00:41:27,610 E vamos ver o que está acontecendo agora. 951 00:41:27,610 --> 00:41:29,840 Assim, por um lado aqui-- e deixe-me fazer 952 00:41:29,840 --> 00:41:32,680 isto é consistente com a anterior example-- por um lado, 953 00:41:32,680 --> 00:41:35,830 lado esquerdo está fazer o que, em Inglês? 954 00:41:35,830 --> 00:41:36,493 Ele é-- 955 00:41:36,493 --> 00:41:37,701 AUDIÊNCIA: Criando um ponteiro. 956 00:41:37,701 --> 00:41:40,830 DAVID J. MALAN: Criando um ponteiro para um int e chamando-x. 957 00:41:40,830 --> 00:41:43,789 Então, é a criação de uma daquelas caixas Eu continuo desenhando na tela de toque. 958 00:41:43,789 --> 00:41:45,913 E agora, na mão direita lado, malloc, é claro, 959 00:41:45,913 --> 00:41:47,420 está alocando um bloco de memória. 960 00:41:47,420 --> 00:41:49,989 E só para ficar claro, como quantidade de memória é, aparentemente, 961 00:41:49,989 --> 00:41:52,030 alocação, se você acabou de tipo de fazer as contas aqui? 962 00:41:52,030 --> 00:41:53,200 963 00:41:53,200 --> 00:41:54,040 >> Portanto, é de 40 bytes. 964 00:41:54,040 --> 00:41:57,400 E eu sei que só porque eu sei que um int, no aparelho CS50, pelo menos, 965 00:41:57,400 --> 00:41:58,060 tem quatro bytes. 966 00:41:58,060 --> 00:41:59,610 Assim, 10 vezes 4 é 40. 967 00:41:59,610 --> 00:42:04,924 Então isso é armazenar um x, o endereço do primeiro de 40 ints que 968 00:42:04,924 --> 00:42:07,340 Foram atribuídos espaço de volta, para trás, para trás, para trás. 969 00:42:07,340 --> 00:42:08,470 >> E isso é o que é importante sobre malloc. 970 00:42:08,470 --> 00:42:11,261 Não é preciso um pouco de memória aqui, um pouco aqui, um pouco aqui. 971 00:42:11,261 --> 00:42:14,220 Dá-lhe um pedaço de memória, contiguamente, a partir da operação 972 00:42:14,220 --> 00:42:15,240 sistema. 973 00:42:15,240 --> 00:42:18,500 >> Agora, o que sobre isso, x suporte de 10 é igual a 0? 974 00:42:18,500 --> 00:42:19,470 Linha arbitrária de código. 975 00:42:19,470 --> 00:42:21,100 Não conseguir qualquer coisa útil. 976 00:42:21,100 --> 00:42:26,128 Mas é interessante, porque x suporte 10--? 977 00:42:26,128 --> 00:42:26,628 Sim? 978 00:42:26,628 --> 00:42:27,912 >> AUDIÊNCIA: [inaudível]? 979 00:42:27,912 --> 00:42:30,500 >> DAVID J. MALAN: x suporte 10 não tem de ser nulo. 980 00:42:30,500 --> 00:42:35,070 O detalhe nulo só entra em jogo com cordas, na extremidade de uma corda. 981 00:42:35,070 --> 00:42:36,700 Mas um bom pensamento. 982 00:42:36,700 --> 00:42:39,615 >> Quão grande é essa matriz, mesmo embora eu tenha alocado 40 bytes? 983 00:42:39,615 --> 00:42:42,560 984 00:42:42,560 --> 00:42:43,690 É 0 a nove, certo? 985 00:42:43,690 --> 00:42:45,120 É 10 ints, no total. 986 00:42:45,120 --> 00:42:48,790 40 bytes, mas 10 ints, indexados de 0 a 0. 987 00:42:48,790 --> 00:42:50,930 >> Então o que é que x suporte de 10? 988 00:42:50,930 --> 00:42:53,090 Na verdade, é um pouco valor de lixo desconhecido. 989 00:42:53,090 --> 00:42:54,780 É a memória que não pertence a mim. 990 00:42:54,780 --> 00:42:59,650 Eu não deveria estar tocando que byte número 41, 42, 43, 44. 991 00:42:59,650 --> 00:43:01,420 Eu estou um pouco longe demais. 992 00:43:01,420 --> 00:43:04,490 >> E, de fato, se eu executar este programa, ele pode muito bem funcionar. 993 00:43:04,490 --> 00:43:05,790 Mas, às vezes, tenhamos sorte. 994 00:43:05,790 --> 00:43:07,706 E assim, apenas para demonstrar isso-- e, francamente, 995 00:43:07,706 --> 00:43:11,000 você nunca sabe antes não ele-- vamos executar este. 996 00:43:11,000 --> 00:43:12,480 Ele não chegou a falhar. 997 00:43:12,480 --> 00:43:15,032 >> Mas se eu mudar isso, para exemplo, ser como 1.000, 998 00:43:15,032 --> 00:43:16,740 para fazer isso realmente deliberada, vamos ver 999 00:43:16,740 --> 00:43:18,710 se nós podemos fazê-lo falhar desta vez. 1000 00:43:18,710 --> 00:43:20,070 OK, ele não caiu. 1001 00:43:20,070 --> 00:43:22,600 Como cerca de 100.000? 1002 00:43:22,600 --> 00:43:25,000 Vamos refazê-lo, e agora executá-lo novamente. 1003 00:43:25,000 --> 00:43:25,500 Está bem. 1004 00:43:25,500 --> 00:43:25,960 Ufa. 1005 00:43:25,960 --> 00:43:26,460 Tudo certo. 1006 00:43:26,460 --> 00:43:29,090 Então, aparentemente, mais uma vez, estes segmentos de memória, por assim dizer, 1007 00:43:29,090 --> 00:43:32,660 são razoavelmente grande, para que possamos ter sorte novamente e novamente. 1008 00:43:32,660 --> 00:43:36,510 Mas no final, quando você chegar ridículo e realmente ir longe na tela, 1009 00:43:36,510 --> 00:43:39,120 você tocar memória que realmente, realmente não pertence a você. 1010 00:43:39,120 --> 00:43:40,870 >> Mas, francamente, estes tipos de erros estão indo 1011 00:43:40,870 --> 00:43:43,020 a ser cada vez mais difícil para descobrir por conta própria. 1012 00:43:43,020 --> 00:43:47,880 Mas, felizmente, como programadores, temos ferramentas que nos permitem fazer isso por nós. 1013 00:43:47,880 --> 00:43:50,140 Portanto, este é, talvez, um dos programas mais feios, 1014 00:43:50,140 --> 00:43:52,060 ainda mais feia do que a produção do gdb. 1015 00:43:52,060 --> 00:43:55,670 Mas sempre tem uma linha ou dois que são super úteis. 1016 00:43:55,670 --> 00:44:00,310 >> Valgrind é um programa que ajuda não depurar um programa, de per si, 1017 00:44:00,310 --> 00:44:03,500 mas encontrar relativas à memória problemas, especificamente. 1018 00:44:03,500 --> 00:44:07,590 Ele será executado automaticamente o código para você e procure pelo menos duas coisas. 1019 00:44:07,590 --> 00:44:10,680 Uma, que você fez algo acidental como a memória de toque 1020 00:44:10,680 --> 00:44:11,980 que não pertence a você? 1021 00:44:11,980 --> 00:44:13,590 Ele irá ajudá-lo a encontrar esses casos. 1022 00:44:13,590 --> 00:44:15,710 >> E dois, ele vai ajudar você encontrar algo chamado 1023 00:44:15,710 --> 00:44:19,270 vazamentos de memória, o que temos completamente ignorado, ingenuamente, 1024 00:44:19,270 --> 00:44:21,380 por algum tempo e felizmente. 1025 00:44:21,380 --> 00:44:23,140 Mas ao que parece, tudo Neste momento, quando 1026 00:44:23,140 --> 00:44:26,620 você chamou getString em muitos de nossos programas, 1027 00:44:26,620 --> 00:44:28,930 você está perguntando o funcionamento sistema para a memória, 1028 00:44:28,930 --> 00:44:32,070 mas você tem qualquer lembrança de cada vez dando-lhe 1029 00:44:32,070 --> 00:44:36,169 para trás, fazendo unalloc, ou livre, como é chamado. 1030 00:44:36,169 --> 00:44:37,960 Não, porque nunca pediu-lhe para fazê-lo. 1031 00:44:37,960 --> 00:44:41,250 >> Mas todo esse tempo, os programas você tem escrito em C 1032 00:44:41,250 --> 00:44:43,800 foram vazamento de memória, pedindo ao funcionamento 1033 00:44:43,800 --> 00:44:46,190 sistema para obter mais e mais memória para cordas e outros enfeites, 1034 00:44:46,190 --> 00:44:47,870 mas nunca entregá-la de volta. 1035 00:44:47,870 --> 00:44:50,080 E agora isso é um pouco de uma simplificação, 1036 00:44:50,080 --> 00:44:53,550 mas se você já executar o seu Mac ou seu PC por algum tempo, a abertura 1037 00:44:53,550 --> 00:44:55,790 muitos programas, talvez fechar programas, 1038 00:44:55,790 --> 00:44:57,795 e mesmo que o seu computador não caiu, 1039 00:44:57,795 --> 00:45:01,690 está ficando muito mais lento, como se fosse realmente 1040 00:45:01,690 --> 00:45:04,290 usando uma grande quantidade de memória ou recursos, apesar de, 1041 00:45:04,290 --> 00:45:06,070 se você não é mesmo tocar o teclado, 1042 00:45:06,070 --> 00:45:10,430 que pode ser-- mas não podia always-- ser que os programas que você está executando 1043 00:45:10,430 --> 00:45:11,920 tem-se vazamentos de memória. 1044 00:45:11,920 --> 00:45:15,645 E eles continuam pedindo o OS para mais e mais memória, mas esquecê-lo, 1045 00:45:15,645 --> 00:45:18,470 na verdade não usá-lo, mas portanto, levando a memória longe 1046 00:45:18,470 --> 00:45:20,500 de outros programas que possam querer isso. 1047 00:45:20,500 --> 00:45:23,940 Então, isso é uma explicação comum. 1048 00:45:23,940 --> 00:45:25,940 Agora aqui é onde Valgrind de saída é completamente 1049 00:45:25,940 --> 00:45:29,290 atroz aos menos e mais confortável iguais. 1050 00:45:29,290 --> 00:45:32,690 Mas o interessante material é bem aqui. 1051 00:45:32,690 --> 00:45:37,060 Ele está me dizendo uma gravação inválido de tamanho quatro acontece neste programa, 1052 00:45:37,060 --> 00:45:40,640 em particular, na linha 21 da memory.c. 1053 00:45:40,640 --> 00:45:45,450 >> Se eu ir para a linha 21, hm, há de fato é uma gravação inválido de tamanho quatro. 1054 00:45:45,450 --> 00:45:46,250 Por tamanho de quatro? 1055 00:45:46,250 --> 00:45:49,500 Bem, este number-- e poderia ser qualquer coisa é um int. 1056 00:45:49,500 --> 00:45:50,450 Então é quatro bytes. 1057 00:45:50,450 --> 00:45:52,550 Então, eu estou colocando quatro bytes onde eles não pertencem. 1058 00:45:52,550 --> 00:45:55,080 Isso é o que Valgrind está realmente me dizendo. 1059 00:45:55,080 --> 00:45:57,600 Além disso, também será me diga, como veremos, 1060 00:45:57,600 --> 00:46:01,490 como você executar isso em um pset futuro, se e quando você já vazou memória, o que de fato 1061 00:46:01,490 --> 00:46:05,300 Eu tenho, porque eu chamei malloc, mas eu realmente não tenho 1062 00:46:05,300 --> 00:46:08,010 chamado, neste caso, livre, que vamos finalmente ver 1063 00:46:08,010 --> 00:46:09,830 é o oposto de malloc. 1064 00:46:09,830 --> 00:46:10,860 1065 00:46:10,860 --> 00:46:12,930 >> Então, agora, eu acho, um exemplo final. 1066 00:46:12,930 --> 00:46:14,050 1067 00:46:14,050 --> 00:46:16,690 Então, este é um pouco mais arcano, mas é talvez 1068 00:46:16,690 --> 00:46:19,180 a maior razão para ter cuidado com a memória, 1069 00:46:19,180 --> 00:46:24,490 ea razão que muitos programas e / ou servidores web, até hoje, 1070 00:46:24,490 --> 00:46:28,200 são tomadas por bandidos em algum lugar na internet que estão de alguma forma 1071 00:46:28,200 --> 00:46:33,390 envio de pacotes falsos para o servidor tentando comprometer suas contas, 1072 00:46:33,390 --> 00:46:36,420 ou ter seus dados, ou apenas geralmente assumir uma máquina. 1073 00:46:36,420 --> 00:46:38,910 Buffer overflow, como o nome sugere, meios 1074 00:46:38,910 --> 00:46:40,740 transbordando não um int, mas um tampão. 1075 00:46:40,740 --> 00:46:43,490 E um buffer é apenas uma maneira elegante de dizer que é um monte de memória. 1076 00:46:43,490 --> 00:46:46,710 >> E, de fato, liguei para uma string antes de buffer, em vez de s. 1077 00:46:46,710 --> 00:46:49,234 Porque se é um buffer, como no sentido YouTube, 1078 00:46:49,234 --> 00:46:52,400 ou quando você está assistindo a um vídeo, você pode ter visto a palavra de tamponamento, 1079 00:46:52,400 --> 00:46:53,040 ponto, ponto, ponto. 1080 00:46:53,040 --> 00:46:54,240 É incrivelmente irritante. 1081 00:46:54,240 --> 00:46:55,990 E isso significa apenas que seu player de vídeo 1082 00:46:55,990 --> 00:46:58,710 está tentando baixar lotes de bytes, os lotes de bytes 1083 00:46:58,710 --> 00:47:00,170 a partir de um vídeo da internet. 1084 00:47:00,170 --> 00:47:02,920 Mas é lento, por isso ele está tentando baixar um monte deles 1085 00:47:02,920 --> 00:47:06,430 para encher um tampão, um recipiente, de modo que você tem suficiente bytes que ele pode, então, 1086 00:47:06,430 --> 00:47:09,174 mostrar-lhe o vídeo, sem parar constantemente. 1087 00:47:09,174 --> 00:47:11,340 Mas acontece, você pode têm uma memória intermédia para esta grande. 1088 00:47:11,340 --> 00:47:15,710 Mas tentar colocar essa quantidade de dados em isso, e muito as coisas ruins podem acontecer. 1089 00:47:15,710 --> 00:47:22,780 Assim, por exemplo, vamos olhar para este teaser final de um exemplo. 1090 00:47:22,780 --> 00:47:24,720 Este é outro programa que, à primeira vista, 1091 00:47:24,720 --> 00:47:26,540 não faz nada super útil. 1092 00:47:26,540 --> 00:47:29,590 Ele tem uma função principal que chama essa função, f. 1093 00:47:29,590 --> 00:47:36,640 E essa função, f, até aqui, tem uma matriz de char, chamado c, de tamanho 12. 1094 00:47:36,640 --> 00:47:39,340 E então ele está usando este nova função chamada strncpy. 1095 00:47:39,340 --> 00:47:40,430 1096 00:47:40,430 --> 00:47:45,190 >> Acontece que, com este simples, simples linha de código, apenas duas linhas, 1097 00:47:45,190 --> 00:47:49,130 temos feito todo o meu programa, e, portanto, todo o meu computador, 1098 00:47:49,130 --> 00:47:54,000 e minha conta de usuário, e meu disco conduzir potencialmente vulnerável a qualquer pessoa 1099 00:47:54,000 --> 00:47:58,170 quem sabe e é bom o suficiente para executar este programa com uma certa linha de comando 1100 00:47:58,170 --> 00:47:58,900 argumento. 1101 00:47:58,900 --> 00:48:03,400 Em outras palavras, se esse cara mau coloca dentro de argvargv [1], digitando 1102 00:48:03,400 --> 00:48:08,750 no teclado muito especialmente criado corda, não abc, 123, mas, essencialmente, 1103 00:48:08,750 --> 00:48:15,180 símbolos binários que representam executável código, um programa que ele ou ela escreveu: 1104 00:48:15,180 --> 00:48:19,190 com este programa simples, que é representativa de milhares de programas 1105 00:48:19,190 --> 00:48:23,610 que são igualmente vulneráveis, ouso dizer, ele ou ela pode vir a excluir todos 1106 00:48:23,610 --> 00:48:26,680 os arquivos no meu disco rígido, obter um alerta piscando para que ele ou ela pode 1107 00:48:26,680 --> 00:48:30,170 digitar comandos por conta própria, enviar e-mail todos os arquivos para mim. 1108 00:48:30,170 --> 00:48:34,660 Qualquer coisa que eu possa fazer, ele ou ela pode fazer com este código. 1109 00:48:34,660 --> 00:48:36,575 >> Não vamos resolver isso bastante ainda. 1110 00:48:36,575 --> 00:48:38,700 E, na verdade, ele vai envolver um pouco de imagem 1111 00:48:38,700 --> 00:48:41,470 como este, que nós vamos em breve para entender tudo melhor. 1112 00:48:41,470 --> 00:48:44,480 Mas por hoje, vamos terminar em o que é, felizmente, um pouco mais 1113 00:48:44,480 --> 00:48:48,360 compreensível piada XKCD, até retomar a próxima vez. 1114 00:48:48,360 --> 00:48:51,100 1115 00:48:51,100 --> 00:48:51,600 Tudo certo. 1116 00:48:51,600 --> 00:48:53,446 Vejo vocês na quarta-feira. 1117 00:48:53,446 --> 00:48:54,754 >> [MÚSICA DE JOGO] 1118 00:48:54,754 --> 00:48:57,790 >> Orador: E agora, no fundo pensamentos, por Daven Farnham. 1119 00:48:57,790 --> 00:49:00,890 1120 00:49:00,890 --> 00:49:04,770 A memória é como pular em uma pilha de folhas de ouro em uma tarde de domingo. 1121 00:49:04,770 --> 00:49:09,000 Vento soprando, lançando o seu hair-- oh, eu sinto falta dos dias when-- 1122 00:49:09,000 --> 00:49:11,100 1123 00:49:11,100 --> 00:49:12,650 >> [Risos] 1124 00:49:12,650 --> 00:49:13,750