Você está na página 1de 263

1

00:00:00,000 --> 00:00:04,482


>[MÚSICA, TOCANDO]

2
00:00:49,370 --> 00:00:53,270
>DAVID MALAN: Tudo bem, esse é o
CS50 e esta é a quarta semana.

3
00:00:53,270 --> 00:00:55,190
>E nas últimas
semanas, tivemos

4
00:00:55,190 --> 00:00:58,217
>uma espécie de treino de iniciação,
ao usar esta linguagem conhecida como C.

5
00:00:58,217 --> 00:01:01,050
>E essas treino de iniciação
na forma da biblioteca CS50.

6
00:01:01,050 --> 00:01:05,580
>E você usa esta biblioteca, é claro,
selecionando e incluindo cs50.h

7
00:01:05,580 --> 00:01:06,650
>sobre o seu código.

8
00:01:06,650 --> 00:01:08,733
>E então, se você pensar
em como o clang funciona,

9
00:01:08,733 --> 00:01:12,080
>você vinculou seu código
via / L CS50.

10
00:01:12,080 --> 00:01:15,290
>Mas tudo isso foi automatizado
para você até agora, usando make.

11
00:01:15,290 --> 00:01:17,900
>Hoje, faremos a transição
do foco da semana passada

12
00:01:17,900 --> 00:01:21,290
>em algoritmos para focar
um pouco mais nas máquinas

13
00:01:21,290 --> 00:01:24,980
>e nas máquinas que agora usamos para
implementar esses algoritmos ainda mais

14
00:01:24,980 --> 00:01:27,410
>poderosamente, quando começamos a
tirar essas treino de iniciação

15
00:01:27,410 --> 00:01:30,840
>e vemos o que está acontecendo
por baixo do capô do seu computador.

16
00:01:30,840 --> 00:01:33,740
>E por mais complicado que alguns
aspectos do C tenham sido,

17
00:01:33,740 --> 00:01:36,320
>já que a programação,
pode ser algo novo para você,

18
00:01:36,320 --> 00:01:39,710
>perceba que não há tanta coisa
acontecendo debaixo do capô

19
00:01:39,710 --> 00:01:42,350
>que precisamos entender
para seguir em frente

20
00:01:42,350 --> 00:01:45,920
>e começar a resolver muito mais
interessantes, mais sofisticados e mais

21
00:01:45,920 --> 00:01:46,820
>problemas divertidos.

22
00:01:46,820 --> 00:01:49,170
>Precisamos apenas de alguns
blocos de construção adicionais.

23
00:01:49,170 --> 00:01:52,340
>E hoje, vamos fazer isso,
primeiro, reaprendendo a contar.

24
00:01:52,340 --> 00:01:55,080
>Aqui, por exemplo, está o que
chamaremos de memória do computador.

25
00:01:55,080 --> 00:01:56,420
>E já vimos essa grade antes.

26
00:01:56,420 --> 00:01:59,420
>E podemos numerar as chamadas de todos
bytes na memória do seu computador.

27
00:01:59,420 --> 00:02:04,550
>Podemos chamar esse byte de número 0, 1,
2, 3, 4, até o byte 15,

28
00:02:04,550 --> 00:02:05,610
>e assim por diante.

29
00:02:05,610 --> 00:02:08,240
>Mas acontece que, ao falar sobre
as memórias dos computadores,

30
00:02:08,240 --> 00:02:10,610
>computadores e cientistas da
computação e programadores

31
00:02:10,610 --> 00:02:13,070
>na verdade, não tendem a usar decimais.

32
00:02:13,070 --> 00:02:15,830
>Eles definitivamente não tendem a
usar binários nesse baixo nível.

33
00:02:15,830 --> 00:02:19,010
>Em vez disso, eles tendem a usar,
por convenção,

34
00:02:19,010 --> 00:02:21,020
>algo chamado hexadecimal.

35
00:02:21,020 --> 00:02:23,210
>Hexadecimal é um sistema
de base diferente que,

36
00:02:23,210 --> 00:02:27,120
>em vez de usar 10 ou
2 dígitos, usa 16.

37
00:02:27,120 --> 00:02:29,360
>E então um cientista da computação,
quando numerar coisas
38
00:02:29,360 --> 00:02:33,980
>como bytes em uma memória de computador,
ainda faria 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

39
00:02:33,980 --> 00:02:37,350
>Mas depois disso, em vez de prosseguir
com o decimal para, digamos, 10,

40
00:02:37,350 --> 00:02:40,970
>11, 12, 13, 14, 15, em vez
disso, convencionalmente,

41
00:02:40,970 --> 00:02:43,260
>começaria a usar algumas
letras do alfabeto.

42
00:02:43,260 --> 00:02:47,270
>E assim, em hexadecimal, este sistema
de base diferente de base 16,

43
00:02:47,270 --> 00:02:48,980
>você começa a contar em 0 ainda.

44
00:02:48,980 --> 00:02:51,130
>Você conta até e até 9.

45
00:02:51,130 --> 00:02:52,880
>Mas quando você quiser
continuar contando mais alto,

46
00:02:52,880 --> 00:02:57,440
>você então vai para A, B, C, D, E e F.

47
00:02:57,440 --> 00:03:02,630
>E a vantagem disso é que, dentro de
hexadecimal - e esse hex implica 16 -

48
00:03:02,630 --> 00:03:08,630
>você tem 16 dígitos individuais
totais, 0 a 9, e também agora, A a F.

49
00:03:08,630 --> 00:03:12,300
>Portanto, não precisamos introduzir
segundos dígitos apenas para contar até 16.

50
00:03:12,300 --> 00:03:14,480
>Podemos usar dígitos
individuais de 0 a F.

51
00:03:14,480 --> 00:03:18,650
>E podemos continuar contando usando
vários dígitos hexadecimais.

52
00:03:18,650 --> 00:03:21,150
>Mas para chegar lá, vamos
introduzir esse vocabulário.

53
00:03:21,150 --> 00:03:23,540
>Então, em binário, é claro,
usamos 0's e 1's.

54
00:03:23,540 --> 00:03:25,690
>Em decimal, é claro,
usamos 0 a 9's.

55
00:03:25,690 --> 00:03:29,360
>E em hexadecimal, para ser claro,
vamos usar de 0 a F's,

56
00:03:29,360 --> 00:03:30,860
>conhecido como base-16.

57
00:03:30,860 --> 00:03:33,320
>E é uma convenção
que usamos de A a F.

58
00:03:33,320 --> 00:03:35,450
>Nós poderíamos ter usado quaisquer outros seis símbolos.

59
00:03:35,450 --> 00:03:37,560
>Mas isso é o que os humanos escolheram.

60
00:03:37,560 --> 00:03:41,090
>Portanto, o hexadecimal funciona de maneira bastante
semelhante ao nosso sistema decimal.

61
00:03:41,090 --> 00:03:45,110
>E é até familiar, agora, com o que você
conhece como sistema binário, como segue.

62
00:03:45,110 --> 00:03:49,370
>Vamos considerar um valor de dois dígitos
usando hexadecimal em vez de decimal

63
00:03:49,370 --> 00:03:50,600
>e em vez de binário.

64
00:03:50,600 --> 00:03:54,680
>Bem, assim como no mundo
decimal, usamos a base 10,

65
00:03:54,680 --> 00:03:57,080
>ou no mundo do binário,
usamos a base 2.

66
00:03:57,080 --> 00:04:01,170
>Vamos usar, agora,
base-16, logo, hexadecimal.

67
00:04:01,170 --> 00:04:02,360
>Portanto, este é 16 na 1.

68
00:04:02,360 --> 00:04:03,590
>Isso é 16 para o -

69
00:04:03,590 --> 00:04:05,090
>desculpe 16 elevado a 0.

70
00:04:05,090 --> 00:04:06,590
>Este é 16 na 1.

71
00:04:06,590 --> 00:04:09,570
>E, claro, se multiplicarmos
isso, é a coluna de uns

72
00:04:09,570 --> 00:04:11,280
>e agora a 16ª coluna.

73
00:04:11,280 --> 00:04:13,550
>E então, se você quiser
contar em hexadecimal,

74
00:04:13,550 --> 00:04:21,290
>você ainda começa com 0, como de costume, então
01, 02, 03, 04, 05, 06, 07, 08, 09.

75
00:04:21,290 --> 00:04:22,910
>E então as coisas ficam interessantes.
76
00:04:22,910 --> 00:04:26,660
>Agora, você não vai eleva a 01,
porque isso seria incorreto.

77
00:04:26,660 --> 00:04:31,880
>01, neste sistema básico, seria
16 vezes 1 mais 1 vez 0.

78
00:04:31,880 --> 00:04:32,960
>Não é isso que queremos.

79
00:04:32,960 --> 00:04:38,930
>Depois que o número que sabemos ser 9,
agora contamos até A, B, C, D, E, F.

80
00:04:38,930 --> 00:04:40,670
>E agora, as coisas ficam interessantes de novo.

81
00:04:40,670 --> 00:04:43,580
>Mas, assim como no sistema decimal,
quando você conta até 99,

82
00:04:43,580 --> 00:04:46,550
>você tem que começar a carregar o 1,
a mesma coisa aqui.

83
00:04:46,550 --> 00:04:49,820
>Se você quiser contar
além de F, carregue o 1.

84
00:04:49,820 --> 00:04:55,340
>E agora, para representar um
valor maior que F, usamos 01,

85
00:04:55,340 --> 00:04:57,350
>que parece 10, mas não é 10.

86
00:04:57,350 --> 00:04:59,675
>Em hexadecimal, é 01.

87
00:04:59,675 --> 00:05:01,880
>16 vezes 1 nos dá 16.

88
00:05:01,880 --> 00:05:03,680
>1 vez 0 nos dá 0.
89
00:05:03,680 --> 00:05:07,050
>E, claro, isso nos dá o número
decimal que agora sabemos que é 16.

90
00:05:07,050 --> 00:05:09,980
>Portanto, não vamos mais introduzir
mais e mais sistemas básicos.

91
00:05:09,980 --> 00:05:12,607
>Mas deixe-me estipular que
apenas usando essas colunas

92
00:05:12,607 --> 00:05:14,690
>que você aprendeu na escola
primária, provavelmente,

93
00:05:14,690 --> 00:05:16,940
>você pode implementar qualquer sistema básico agora.

94
00:05:16,940 --> 00:05:19,310
>Acontece que, no mundo
dos computadores,

95
00:05:19,310 --> 00:05:22,295
>e hoje no mundo da memória, e
em breve, também arquivos,

96
00:05:22,295 --> 00:05:24,170
>vai ser muito
convencional ser

97
00:05:24,170 --> 00:05:26,990
>capaz de reconhecer e usar hexadecimal.

98
00:05:26,990 --> 00:05:29,530
>E, há uma razão pela qual
os humanos gostam de hexadecimais,

99
00:05:29,530 --> 00:05:30,530
>ou pelo menos alguns humanos.

100
00:05:30,530 --> 00:05:36,827
>Os cientistas da computação lembram
que se contarmos até FF, neste caso,

101
00:05:36,827 --> 00:05:38,160
>ainda faríamos a mesma matemática.

102
00:05:38,160 --> 00:05:44,060
>Então, 16 vezes 15 mais 1 vez
15 vai nos dar, isso,

103
00:05:44,060 --> 00:05:49,210
>ou, claro, 240 mais 15 ou 255.

104
00:05:49,210 --> 00:05:50,460
>E eu fiz isso muito rapidamente.

105
00:05:50,460 --> 00:05:53,000
>Mas esse é o tipo de matemática
do ensino fundamental de multiplicação

106
00:05:53,000 --> 00:05:55,730
>a coluna pelo valor que
está nela, onde novamente,

107
00:05:55,730 --> 00:06:00,140
>cada um desses Fs é como agora
expressamos 15 usando um único dígito.

108
00:06:00,140 --> 00:06:02,480
>Mas lembre-se de que vimos 255 antes.

109
00:06:02,480 --> 00:06:04,610
>Quando falamos sobre binário
há algumas semanas,

110
00:06:04,610 --> 00:06:12,450
>255 também passou a ser o padrão que
vemos aqui, oito bits 1 usando binário.

111
00:06:12,450 --> 00:06:15,278
>E então, a razão pela qual os cientistas
da computação tendem ao hexadecimal,

112
00:06:15,278 --> 00:06:17,570
>é que, em oito bits, há

113
00:06:17,570 --> 00:06:20,000
>dois pares aqui, como quatro à
esquerda, quatro à direita.
114
00:06:20,000 --> 00:06:22,340
>Se dermos um jeito
nessas coisas,

115
00:06:22,340 --> 00:06:25,520
>acontece que, porque
hexadecimal permite

116
00:06:25,520 --> 00:06:28,730
>a você representar
16 valores possíveis, é

117
00:06:28,730 --> 00:06:32,750
>um sistema perfeito para
representar quatro bits por vez.

118
00:06:32,750 --> 00:06:36,980
>Afinal, se você tem quatro bits aqui,
cada um dos quais pode ser 0 ou 1,

119
00:06:36,980 --> 00:06:42,020
>ou seja, 2 vezes 2 vezes 2 vezes 2
valores possíveis para cada um deles,

120
00:06:42,020 --> 00:06:45,740
>ou 16 valores totais, ou seja,
no mundo dos computadores,

121
00:06:45,740 --> 00:06:48,560
>se você quiser falar em
unidades de quatro bits,

122
00:06:48,560 --> 00:06:51,590
>é conveniente
usar hexadecimal em vez disso,

123
00:06:51,590 --> 00:06:56,270
>apenas porque, convenientemente,
um dígito hexadecimal passa a ser

124
00:06:56,270 --> 00:07:00,590
>equivalente a quatro dígitos
binários, 0's e 1's.

125
00:07:00,590 --> 00:07:05,160
>Portanto, 0, 0, 0, 0, todo
o caminho até 1, 1, 1, 1.
126
00:07:05,160 --> 00:07:06,320
>Então, por que os humanos fazem isso?

127
00:07:06,320 --> 00:07:09,240
>Só agora é a convenção humana
por causa dessa conveniência.

128
00:07:09,240 --> 00:07:11,760
>Agora, alguns de vocês podem muito
bem ter visto hexadecimal antes.

129
00:07:11,760 --> 00:07:14,660
>Na verdade, lembre-se de nossa
discussão na semana 0 de RGB,

130
00:07:14,660 --> 00:07:17,660
>onde discutimos a
representação de cores usando

131
00:07:17,660 --> 00:07:19,860
>alguma quantidade de vermelho, verde e azul.

132
00:07:19,860 --> 00:07:21,720
>E na época, usamos este exemplo.

133
00:07:21,720 --> 00:07:24,080
>Pegamos nosso exemplo fora do contexto.

134
00:07:24,080 --> 00:07:27,560
>E em vez de usar oi como
uma string de texto,

135
00:07:27,560 --> 00:07:33,410
>reinterpretamos 72, 73 e
33 como uma sequência de cores.

136
00:07:33,410 --> 00:07:34,550
>Quanto vermelho você quer?

137
00:07:34,550 --> 00:07:35,720
>Quanto verde você quer?

138
00:07:35,720 --> 00:07:36,860
>Quanto azul você quer?
139
00:07:36,860 --> 00:07:37,820
>E isso é bom.

140
00:07:37,820 --> 00:07:41,060
>É perfeitamente normal pensar e
se expressar em termos decimais.

141
00:07:41,060 --> 00:07:44,270
>Mas os cientistas da computação tendem a não
fazer dessa forma no contexto das cores

142
00:07:44,270 --> 00:07:45,790
>e no contexto da memória.

143
00:07:45,790 --> 00:07:49,160
>Em vez disso, eles tendem a
usar algo chamado hexadecimal.

144
00:07:49,160 --> 00:07:51,590
>E hexadecimal, aqui,
seria apenas

145
00:07:51,590 --> 00:07:57,860
>mudar esses valores de 72,
73, 33, para o hexadecimal equivalente

146
00:07:57,860 --> 00:07:58,533
>em representação.

147
00:07:58,533 --> 00:08:00,200
>E não vamos nos incomodar em fazer as contas aqui.

148
00:08:00,200 --> 00:08:04,340
>Mas deixe-me estipular que
72, 73, 33 em decimal

149
00:08:04,340 --> 00:08:10,262
>é a mesma coisa que 48,
49, 21 em hexadecimal.

150
00:08:10,262 --> 00:08:12,470
>Agora, obviamente, se você
olhar para esses três números,

151
00:08:12,470 --> 00:08:15,980
>não é nada óbvio se você está
olhando para dígitos hexadecimais

152
00:08:15,980 --> 00:08:21,080
>ou dígitos decimais, porque eles
usam o mesmo subconjunto, de 0 a 9.

153
00:08:21,080 --> 00:08:23,240
>E então uma convenção também,
no mundo do Computação,

154
00:08:23,240 --> 00:08:25,850
>é que sempre que você representa
dígitos hexadecimais,

155
00:08:25,850 --> 00:08:29,300
>você tende a prefixá-los,
porque sim, com 0x.

156
00:08:29,300 --> 00:08:32,179
>E não há significado
matemático para 0 ou x.

157
00:08:32,179 --> 00:08:35,419
>É apenas um prefixo que você coloca lá
para deixar claro para o visualizador

158
00:08:35,419 --> 00:08:38,299
>que esses são dígitos hexadecimais,
mesmo se pudessem de outra forma

159
00:08:38,299 --> 00:08:40,490
>parecer dígitos decimais.

160
00:08:40,490 --> 00:08:41,940
>Então, aonde vamos com isso?

161
00:08:41,940 --> 00:08:43,857
>Bem, aqueles de vocês que
podem ter experimentado

162
00:08:43,857 --> 00:08:46,850
>no passado, criando suas próprias
páginas da web e tornando-as coloridas,

163
00:08:46,850 --> 00:08:50,450
>ou aqueles de vocês que são artistas e
usaram programas como o Photoshop,
164
00:08:50,450 --> 00:08:53,190
>você já viu esses códigos antes.

165
00:08:53,190 --> 00:08:55,940
>Na verdade, aqui estão algumas
capturas de tela do próprio Photoshop.

166
00:08:55,940 --> 00:08:59,190
>Se você clicar em uma cor no
Photoshop e abrir esta janela,

167
00:08:59,190 --> 00:09:02,300
>você pode mudar a cor que
está desenhando na tela

168
00:09:02,300 --> 00:09:04,970
>qualquer uma das cores do arco-íris.

169
00:09:04,970 --> 00:09:07,470
>Mas de forma mais precisa,
se você olhar aqui embaixo,

170
00:09:07,470 --> 00:09:09,620
>você pode ver
esses códigos hexadecimais,

171
00:09:09,620 --> 00:09:11,990
>porque se tornou uma convenção
humana ao longo dos anos

172
00:09:11,990 --> 00:09:15,630
>usar hexadecimal para representar
diferentes quantidades de vermelho, verde,

173
00:09:15,630 --> 00:09:16,320
>e azul.

174
00:09:16,320 --> 00:09:23,435
>Então, se você não tem vermelho, verde, azul,
representado como 000000,

175
00:09:23,435 --> 00:09:26,060
>bem, isso vai lhe dar a cor que
conhecemos aqui como preto.

176
00:09:26,060 --> 00:09:29,510
>É uma espécie de ausência de qualquer
comprimento de onda de luz ali.

177
00:09:29,510 --> 00:09:33,470
>Se, por outro lado, você alterar
todos esses seis dígitos

178
00:09:33,470 --> 00:09:38,810
>para o maior valor possível, que,
novamente, é F. O intervalo em hexadecimal 0

179
00:09:38,810 --> 00:09:42,890
>a F, em decimal,
sendo 0 a 15, bem,

180
00:09:42,890 --> 00:09:46,800
>com FFFFFF, é muito vermelho,
muito verde, muito azul.

181
00:09:46,800 --> 00:09:48,800
>E quando você combina esses
comprimentos de onda de luz,

182
00:09:48,800 --> 00:09:51,200
>você obtém a cor que vemos aqui como branco.

183
00:09:51,200 --> 00:09:53,480
>E você pode imaginar, agora,
combinando diferentes quantidades

184
00:09:53,480 --> 00:09:54,930
>de vermelho, verde ou azul.

185
00:09:54,930 --> 00:10:00,740
>Então, por exemplo, em hexadecimal,
FF0000, é a cor que conhecemos como vermelho.

186
00:10:00,740 --> 00:10:05,270
>00FF00 é a cor que conhecemos como verde.

187
00:10:05,270 --> 00:10:09,630
>E, finalmente, 0000FF é a cor que
conhecemos como azul, porque, novamente,

188
00:10:09,630 --> 00:10:14,240
>o sistema que os programadores e artistas
frequentemente, mas nem sempre usam, é de fato,

189
00:10:14,240 --> 00:10:17,710
>este sistema de RGB para
vermelho, verde e azul.

190
00:10:17,710 --> 00:10:19,460
>Então, nós introduzimos
isso aqui não porque você

191
00:10:19,460 --> 00:10:21,810
>tem que começar a pensar de forma
diferente, porque, novamente,

192
00:10:21,810 --> 00:10:24,560
>o mecanismo matemático
é o mesmo da semana 0.

193
00:10:24,560 --> 00:10:28,970
>Mas você vai começar a ver números
em exemplos, em programas,

194
00:10:28,970 --> 00:10:32,900
>como apenas aparecendo em hexadecimal
por convenção, em oposição a

195
00:10:32,900 --> 00:10:35,550
>sendo interpretado como decimal.

196
00:10:35,550 --> 00:10:37,880
>Então, se considerarmos, agora,
a memória do nosso computador,

197
00:10:37,880 --> 00:10:40,610
>vamos agora começar a pensar
em toda essa tela de memória,

198
00:10:40,610 --> 00:10:43,010
>todos esses bytes dentro da
memória do nosso computador,

199
00:10:43,010 --> 00:10:46,700
>como sendo inumeráveis como 0,
1, 2, até F.

200
00:10:46,700 --> 00:10:53,750
>E então, se continuarmos contando, podemos
ir para 10, 11, 12, 13, 14, 15, 16, 17, 18,

201
00:10:53,750 --> 00:10:58,850
>19, 1A, 1B, 1C, 1D e assim por diante.

202
00:10:58,850 --> 00:11:00,790
>E tudo bem se não
for tão óbvio,

203
00:11:00,790 --> 00:11:03,670
>quando você olha para essas coisas,
quais são os equivalentes decimais.

204
00:11:03,670 --> 00:11:04,690
>Isso não é um problema.

205
00:11:04,690 --> 00:11:09,130
>É apenas uma maneira diferente de
pensar sobre os locais, neste caso,

206
00:11:09,130 --> 00:11:13,480
>da memória de um computador, ou a
representação de uma cor ou outra.

207
00:11:13,480 --> 00:11:19,480
>Tudo bem, vamos agora usar isso
como um exemplo de oportunidade,

208
00:11:19,480 --> 00:11:22,690
>em vez disso, considerar o que está
sendo armazenado na memória do nosso computador.

209
00:11:22,690 --> 00:11:26,320
>E para ser claro, vou começar a prefixar
todos esses endereços de memória,

210
00:11:26,320 --> 00:11:29,890
>por assim dizer, com 0x, apenas para deixar
claro que agora estamos falando,

211
00:11:29,890 --> 00:11:31,480
>em termos de 0's e 1's.

212
00:11:31,480 --> 00:11:32,980
>Portanto, aqui está uma linha de código simples.

213
00:11:32,980 --> 00:11:35,147
>Fora do contexto, precisaríamos,
na verdade, colocar isso

214
00:11:35,147 --> 00:11:37,910
>no main ou algum outro programa para
fazer qualquer coisa com ele.

215
00:11:37,910 --> 00:11:39,702
>Mas já vimos isso
muitas vezes, agora,

216
00:11:39,702 --> 00:11:42,760
>onde você declara uma variável,
por exemplo, n para número.

217
00:11:42,760 --> 00:11:44,830
>Declare-o como um int para seu tipo.

218
00:11:44,830 --> 00:11:47,170
>E então, talvez,
até mesmo atribua um valor a ele.

219
00:11:47,170 --> 00:11:51,520
>Bem, o que está acontecendo quando
usamos esse tipo de código em nosso computador?

220
00:11:51,520 --> 00:11:54,760
>Bem, vamos prosseguir e transformar
isso em um programa real.

221
00:11:54,760 --> 00:11:57,970
>Vamos criar um arquivo
chamado address.c porque eu

222
00:11:57,970 --> 00:12:01,300
>deseja começar a experimentar alguns
endereços na memória do computador.

223
00:12:01,300 --> 00:12:04,180
>Vou prosseguir e incluir
o padrão io ponto h.

224
00:12:04,180 --> 00:12:06,460
>Vou criar int main void.

225
00:12:06,460 --> 00:12:08,890
>E aqui embaixo, vou prosseguir
e declarar exatamente

226
00:12:08,890 --> 00:12:10,915
>essa variável, int n é igual a 50.

227
00:12:10,915 --> 00:12:15,820
>E então vou prosseguir e imprimir, com
percentual i e uma \ 0,

228
00:12:15,820 --> 00:12:17,230
>o valor de n.

229
00:12:17,230 --> 00:12:19,930
>Então nada de interessante aí,
nada muito complicado.

230
00:12:19,930 --> 00:12:21,790
>Vou seguir em frente e make address.

231
00:12:21,790 --> 00:12:24,123
>E então vou prosseguir e fazer
./ address.

232
00:12:24,123 --> 00:12:26,380
>E, claro, como na primeira
semana, devemos esperar

233
00:12:26,380 --> 00:12:27,930
>apenas o número 50.

234
00:12:27,930 --> 00:12:31,570
>Mas hoje, vamos lhe dar mais algumas
ferramentas com as quais você pode

235
00:12:31,570 --> 00:12:33,880
>vasculhar a
memória do seu computador.

236
00:12:33,880 --> 00:12:35,950
>Mas vamos primeiro considerar
esta linha de código

237
00:12:35,950 --> 00:12:38,240
>no contexto do hardware
do seu computador.
238
00:12:38,240 --> 00:12:41,200
>Então, se você estiver escrevendo um
programa com uma linha de código como esta,

239
00:12:41,200 --> 00:12:44,500
>que n precisa estar em algum lugar
na memória do seu computador.

240
00:12:44,500 --> 00:12:47,870
>Esse 50 precisa ser colocado em algum
lugar na memória do seu computador.

241
00:12:47,870 --> 00:12:51,010
>Então, se nós, novamente, considerarmos
que isso seja apenas parte da

242
00:12:51,010 --> 00:12:55,000
>memória, algumas dezenas de bytes, bem,
suponha que essa variável, n,

243
00:12:55,000 --> 00:12:57,130
>acaba aqui embaixo.

244
00:12:57,130 --> 00:13:01,570
>Eu desenhei deliberadamente n ocupando
quatro bytes, quatro quadrados, porque nós

245
00:13:01,570 --> 00:13:05,830
>chamamos a isso de um número inteiro, normalmente,
pelo menos em CS50 IDE e sistemas modernos,

246
00:13:05,830 --> 00:13:07,370
>tende a ter quatro bytes.

247
00:13:07,370 --> 00:13:10,630
>Então, fiz questão de preencher
quatro caixas completas.

248
00:13:10,630 --> 00:13:13,940
>E então o valor pode ser 50 que
está armazenado lá.

249
00:13:13,940 --> 00:13:17,890
>Bem, acontece que na memória
do seu computador, novamente,

250
00:13:17,890 --> 00:13:20,660
>existem esses endereços que
estão implicitamente lá.

251
00:13:20,660 --> 00:13:23,530
>Portanto, embora, sim, podemos
nos referir a esta variável, n,

252
00:13:23,530 --> 00:13:26,620
>com base no nome da variável
que dei em meu código,

253
00:13:26,620 --> 00:13:30,940
>certamente essa variável existe em
um local específico na memória.

254
00:13:30,940 --> 00:13:32,530
>Não sei de imediato onde está.

255
00:13:32,530 --> 00:13:38,410
>Mas deixe-me apenas propor que talvez
esteja na localização 0x12345678, apenas

256
00:13:38,410 --> 00:13:39,550
>um endereço arbitrário.

257
00:13:39,550 --> 00:13:41,690
>Não tenho ideia, na
verdade, de onde está.

258
00:13:41,690 --> 00:13:44,860
>Mas certamente tem um endereço,
porque cada um desses quadrados

259
00:13:44,860 --> 00:13:49,540
>dentro da memória do seu computador tem um
endereço, um identificador único como 0, 1,

260
00:13:49,540 --> 00:13:50,750
>2, e assim por diante.

261
00:13:50,750 --> 00:13:56,710
>Talvez o 50 tenha terminado no
endereço de memória 0x12345678.

262
00:13:56,710 --> 00:14:01,750
>Bem, isso é o legal sobre C, é que
podemos começar a ver isso,

263
00:14:01,750 --> 00:14:03,020
>sem trocadilhos.

264
00:14:03,020 --> 00:14:05,080
>Então, deixe-me ir em frente
e modificar este programa

265
00:14:05,080 --> 00:14:07,480
>e introduzir um pouco
de nova sintaxe que

266
00:14:07,480 --> 00:14:11,510
>nos permitirá começar a vasculhar o
interior da memória do seu computador

267
00:14:11,510 --> 00:14:14,830
>para que possamos ver o
que está acontecendo por baixo.

268
00:14:14,830 --> 00:14:17,710
>Portanto, vou prosseguir e alterar
este programa para fazer isso.

269
00:14:17,710 --> 00:14:19,585
>Vou prosseguir e
dizer, quer saber?

270
00:14:19,585 --> 00:14:23,590
>Não imprima apenas o valor,
n, que, claro, é 50.

271
00:14:23,590 --> 00:14:28,060
>Vamos ver, apenas por curiosidade,
qual é o endereço real de n.

272
00:14:28,060 --> 00:14:31,300
>E para fazer isso hoje, vamos
apresentar uma nova parte da sintaxe,

273
00:14:31,300 --> 00:14:33,070
>que por acaso é esta aqui.

274
00:14:33,070 --> 00:14:37,360
>Existem dois novos operadores, hoje, em C.
O primeiro é um & - &, que
275
00:14:37,360 --> 00:14:39,580
>não representa um e lógico.

276
00:14:39,580 --> 00:14:42,100
>Lembre-se de algumas semanas
atrás, vimos que se você

277
00:14:42,100 --> 00:14:46,840
>deseja combinar expressões booleanas,
isso e aquilo, você usa dois & - &&.

278
00:14:46,840 --> 00:14:51,040
>É uma coincidência infeliz que
um & comercial, sozinho,

279
00:14:51,040 --> 00:14:52,630
>significará algo diferente hoje.

280
00:14:52,630 --> 00:14:56,830
>Especificamente, esse &
será nosso endereço do operador.

281
00:14:56,830 --> 00:15:02,590
>Simplesmente prefixando qualquer nome de variável
com um &, podemos dizer ao C,

282
00:15:02,590 --> 00:15:06,520
>diga-me em que endereço esta
variável está armazenada.

283
00:15:06,520 --> 00:15:10,180
>E esta asterisco, não deve ser
confundida com multiplicação,

284
00:15:10,180 --> 00:15:12,880
>também tem outro significado
no contexto atual.

285
00:15:12,880 --> 00:15:15,310
>Quando você usa este
asterisco, você pode

286
00:15:15,310 --> 00:15:19,910
>dizer ao seu programa para olhar dentro
de um endereço de memória específico.
287
00:15:19,910 --> 00:15:23,500
>Portanto, o & informa em
que endereço está uma variável.

288
00:15:23,500 --> 00:15:27,310
>O operador asterisco, também conhecido
como operador de desreferência,

289
00:15:27,310 --> 00:15:30,190
>significa, vá para o seguinte endereço.

290
00:15:30,190 --> 00:15:32,050
>Então, meio que são operações reversas.

291
00:15:32,050 --> 00:15:33,400
>Descobre-se o endereço.

292
00:15:33,400 --> 00:15:35,240
>Um vai para o endereço.

293
00:15:35,240 --> 00:15:37,850
>E então vamos ver isso de verdade aqui.

294
00:15:37,850 --> 00:15:43,070
>Vamos prosseguir e alterar meu n em
meu programa aqui para & n.

295
00:15:43,070 --> 00:15:48,980
>Então, eu quero imprimir, não o
número em n, mas o endereço de n.

296
00:15:48,980 --> 00:15:50,870
>E agora, como imprimo um endereço?

297
00:15:50,870 --> 00:15:52,170
>Bem, é um número.

298
00:15:52,170 --> 00:15:56,690
>Mas, na verdade, printf suporta um código
de formato diferente para endereços.

299
00:15:56,690 --> 00:15:59,840
>Você pode fazer % p,
por razões que veremos em breve,

300
00:15:59,840 --> 00:16:02,510
>que diz para imprimir o
endereço desta variável

301
00:16:02,510 --> 00:16:05,375
>e interpretá-lo como hexadecimal,
novamente, por convenção.

302
00:16:05,375 --> 00:16:07,250
>Vou prosseguir e
make address now

303
00:16:07,250 --> 00:16:10,530
>depois de fazer apenas duas
alterações neste arquivo.

304
00:16:10,530 --> 00:16:12,350
>Tudo parece compilar bem.

305
00:16:12,350 --> 00:16:14,150
>Agora, vou prosseguir e
executar o endereço.

306
00:16:14,150 --> 00:16:17,210
>E veremos que, neste
programa específico,

307
00:16:17,210 --> 00:16:21,620
>address.c, por qualquer
motivo, essa variável, n,

308
00:16:21,620 --> 00:16:30,110
>acabou na localização
maluca 0x7ffd80792f7c.

309
00:16:30,110 --> 00:16:31,160
>Agora, isso é útil?

310
00:16:31,160 --> 00:16:32,870
>Não na prática.

311
00:16:32,870 --> 00:16:36,530
>Faremos com que isso se torne útil
aproveitando esses endereços.

312
00:16:36,530 --> 00:16:38,900
>Mas o endereço específico
não é interessante.

313
00:16:38,900 --> 00:16:40,070
>Estou olhando para este número.

314
00:16:40,070 --> 00:16:41,993
>Não tenho ideia do que é
esse número em decimal.

315
00:16:41,993 --> 00:16:44,660
>Eu teria que fazer as contas ou
apenas pesquisar um conversor no Google

316
00:16:44,660 --> 00:16:45,660
>fazendo isso por mim.

317
00:16:45,660 --> 00:16:47,420
>Então, novamente, essa não
é a parte interessante.

318
00:16:47,420 --> 00:16:50,420
>O fato de estar em hexadecimal é
apenas um detalhe de implementação.

319
00:16:50,420 --> 00:16:54,450
>Acontece que representa a
localização desta variável.

320
00:16:54,450 --> 00:16:58,230
>E, novamente, não queremos
fazer isso.

321
00:16:58,230 --> 00:17:00,830
>Mas só para deixar claro
que um desses operadores,

322
00:17:00,830 --> 00:17:02,330
>o & obtém o endereço.

323
00:17:02,330 --> 00:17:05,089
>E o operador asterisco
vai para um endereço.

324
00:17:05,089 --> 00:17:07,160
>Podemos desfazer
os efeitos dessas coisas.
325
00:17:07,160 --> 00:17:13,010
>Por exemplo, se eu imprimir agora, não e
comercial n, mas apenas por curiosidade,

326
00:17:13,010 --> 00:17:18,170
>asterisco & n, posso
desfazer os efeitos desse operador.

327
00:17:18,170 --> 00:17:21,170
>& n dirá,
qual é o endereço de n?

328
00:17:21,170 --> 00:17:25,349
>& asterisco n vai
dizer, vá para esse endereço.

329
00:17:25,349 --> 00:17:29,360
>Portanto, este é um exercício meio inútil,
porque se eu só quero o que está em n,

330
00:17:29,360 --> 00:17:32,120
>Eu posso, obviamente,
imprimir n como começamos.

331
00:17:32,120 --> 00:17:34,560
>Mas, novamente, apenas como
um exercício intelectual,

332
00:17:34,560 --> 00:17:38,750
>se eu prefixo n com o endereço do
operador e, em seguida, uso o asterisco

333
00:17:38,750 --> 00:17:42,830
>e digo, vá para aquele endereço,
é exatamente a mesma coisa

334
00:17:42,830 --> 00:17:44,280
>como apenas imprimir n em si.

335
00:17:44,280 --> 00:17:46,640
>Então, deixe-me mudar
de volta para um inteiro.

336
00:17:46,640 --> 00:17:50,060
>Em vez de % p, deixe-me ir
em frente e make address now,
337
00:17:50,060 --> 00:17:52,100
>parece compilar OK e executar o endereço.

338
00:17:52,100 --> 00:17:53,885
>E pronto, estamos de volta aos 50.

339
00:17:53,885 --> 00:17:57,050
>Por mais estranha que a sintaxe
de hoje possa começar a parecer,

340
00:17:57,050 --> 00:17:59,330
>perceber que esses operadores,
afinal,

341
00:17:59,330 --> 00:18:01,833
>são relativamente simples no que fazem.

342
00:18:01,833 --> 00:18:05,000
>E se você entender que um meio
que desfaz os efeitos do outro,

343
00:18:05,000 --> 00:18:08,360
>podemos começar a construir alguns
programas bastante interessantes com eles.

344
00:18:08,360 --> 00:18:11,870
>E faremos isso aproveitando
um tipo especial de variável,

345
00:18:11,870 --> 00:18:13,910
>uma variável chamada ponteiro.

346
00:18:13,910 --> 00:18:16,670
>E existe aquele p em % p.

347
00:18:16,670 --> 00:18:22,240
>Um ponteiro é uma variável que contém
o endereço de algum outro valor.

348
00:18:22,240 --> 00:18:23,790
>Então, já vimos números inteiros antes.

349
00:18:23,790 --> 00:18:27,770
>Vimos floats, chars, strings
e outros tipos também.
350
00:18:27,770 --> 00:18:31,430
>Ponteiros, agora, são apenas
um tipo diferente de variável

351
00:18:31,430 --> 00:18:34,640
>que armazenam o endereço de algum valor.

352
00:18:34,640 --> 00:18:40,250
>E você pode ter ponteiros para inteiros,
ponteiros para chars, ponteiros para booleanos,

353
00:18:40,250 --> 00:18:41,870
>ou qualquer outro tipo de dados.

354
00:18:41,870 --> 00:18:45,980
>Um ponteiro faz referência
ao tipo específico do valor

355
00:18:45,980 --> 00:18:48,223
>a que se refere.

356
00:18:48,223 --> 00:18:49,640
>Então, vamos ver isso mais concretamente.

357
00:18:49,640 --> 00:18:51,620
>voltando, agora, ao meu programa aqui.

358
00:18:51,620 --> 00:18:53,840
>E deixe-me apresentar
outra variável aqui.

359
00:18:53,840 --> 00:18:58,430
>Em vez de imprimir imediatamente
algo como n, deixe-me prosseguir

360
00:18:58,430 --> 00:19:02,870
>e introduzir uma segunda
variável do tipo int asterisco.

361
00:19:02,870 --> 00:19:06,860
>E isso, devo admitir, é provavelmente
a parte mais confusa da sintaxe C

362
00:19:06,860 --> 00:19:09,860
>que iremos, em geral, ver,
só porque, meu Deus, asterisco é agora
363
00:19:09,860 --> 00:19:13,220
>usado para multiplicação, para ir
para um endereço, e também, agora,

364
00:19:13,220 --> 00:19:14,610
>declarar uma variável.

365
00:19:14,610 --> 00:19:17,120
>Esta não é, sem dúvida, a
melhor decisão de design.

366
00:19:17,120 --> 00:19:18,350
>Mas foi feito há décadas.

367
00:19:18,350 --> 00:19:19,730
>Então é isso que temos.

368
00:19:19,730 --> 00:19:26,240
>Mas se eu fizer int asterisco p é igual a e
comercial n, agora, o que posso fazer aqui,

369
00:19:26,240 --> 00:19:31,770
>é imprimir o endereço de n armazenando-o
temporariamente em uma variável.

370
00:19:31,770 --> 00:19:33,830
>Portanto, não estou fazendo nada novo ainda.

371
00:19:33,830 --> 00:19:36,020
>Ainda estou declarando
na linha 5, um inteiro

372
00:19:36,020 --> 00:19:37,910
>chamado n, atribuindo no valor 50.

373
00:19:37,910 --> 00:19:42,260
>O que há de novo agora na linha 6 é que estou
introduzindo um novo tipo de variável.

374
00:19:42,260 --> 00:19:44,210
>Esse tipo de variável é
conhecida como ponteiro.

375
00:19:44,210 --> 00:19:48,410
>Um ponteiro, novamente, é uma variável
que armazena o endereço de algum valor.

376
00:19:48,410 --> 00:19:53,240
>E a sintaxe, reconhecidamente estranha,
para declarar um ponteiro para um inteiro,

377
00:19:53,240 --> 00:19:57,560
>é literalmente dizer int, porque esse é
o tipo para o qual você está apontando,

378
00:19:57,560 --> 00:20:00,350
>asterisco e, em seguida, o nome
da variável que deseja criar.

379
00:20:00,350 --> 00:20:03,320
>E eu poderia chamar isso de qualquer coisa, mas
vou chamar de p para mantê-lo sucinto.

380
00:20:03,320 --> 00:20:05,120
>E, novamente, do lado
direito do sinal de igual

381
00:20:05,120 --> 00:20:06,620
>é o mesmo operador de antes.

382
00:20:06,620 --> 00:20:10,040
>Se você quiser descobrir qual é o
endereço de n, é & n.

383
00:20:10,040 --> 00:20:14,450
>E para que possamos armazenar esse endereço,
agora, em algum lugar de longo prazo.

384
00:20:14,450 --> 00:20:18,110
>Antes, acabei de passar o
& n e printf fez o que costuma fazer.

385
00:20:18,110 --> 00:20:23,120
>Agora, estou temporariamente, na linha 6,
armazenando esse endereço em uma nova variável

386
00:20:23,120 --> 00:20:24,470
>chamada p.

387
00:20:24,470 --> 00:20:28,910
>E seu tipo é tecnicamente int asterisco,
é o que um programador diria.
388
00:20:28,910 --> 00:20:33,680
>Portanto, seria incorreto dizer que
int p é igual a & n.

389
00:20:33,680 --> 00:20:35,780
>E, nosso compilador,
Clang, não vai gostar disso.

390
00:20:35,780 --> 00:20:38,370
>Provavelmente, não permitirá
que você compile o código.

391
00:20:38,370 --> 00:20:43,160
>E então, em vez disso, pretendo deixar
claro que sei o que estou fazendo.

392
00:20:43,160 --> 00:20:48,450
>Estou armazenando o endereço de um int,
não de um inteiro, por assim dizer.

393
00:20:48,450 --> 00:20:53,040
>Então, se eu for em frente agora e
salvar isso, recompilar com make address.

394
00:20:53,040 --> 00:20:55,530
>E observe, eu mudei uma
linha do código 2 antes.

395
00:20:55,530 --> 00:20:59,400
>Voltei para a % p para
imprimir um ponteiro que é um endereço.

396
00:20:59,400 --> 00:21:02,490
>E estou apontando o valor de
p, não mais o valor de n.

397
00:21:02,490 --> 00:21:07,050
>Se eu agora executar o endereço de barra pontilhada,
voila, há aquele endereço enigmático.

398
00:21:07,050 --> 00:21:09,300
>E esses endereços podem muito
bem mudar com o tempo.

399
00:21:09,300 --> 00:21:11,640
>Dependendo do que está acontecendo
dentro do seu programa

400
00:21:11,640 --> 00:21:15,390
>ou outras coisas no sistema, esses
endereços podem ser diferentes a cada vez.

401
00:21:15,390 --> 00:21:18,060
>E isso é esperado e não algo
em que se possa confiar.

402
00:21:18,060 --> 00:21:20,250
>Mas é claramente algum endereço
criptográfico aleatório,

403
00:21:20,250 --> 00:21:24,400
>semelhante ao meu arbitrário
0x12345678 antes.

404
00:21:24,400 --> 00:21:26,310
>Mas agora, vamos apenas desfazer esta operação.

405
00:21:26,310 --> 00:21:30,120
>Só para que possamos fechar o
círculo aqui, deixe-me propor

406
00:21:30,120 --> 00:21:33,495
>como posso imprimir o valor de n.

407
00:21:33,495 --> 00:21:35,370
>E deixe-me chamar alguém
para isso, se puder.

408
00:21:35,370 --> 00:21:41,640
>Se meu objetivo, agora, na linha 7, não é
mais imprimir o endereço de n, mas imprimir

409
00:21:41,640 --> 00:21:43,972
>o próprio n usando p.

410
00:21:43,972 --> 00:21:45,930
>Vou seguir em frente e
mudar, preventivamente,

411
00:21:45,930 --> 00:21:47,820
>o código de formato em % i.

412
00:21:47,820 --> 00:21:51,660
>E uma notação abreviada seria,
obviamente, basta imprimir n.

413
00:21:51,660 --> 00:21:53,610
>Mas suponha que eu não
queira imprimir n para este

414
00:21:53,610 --> 00:22:02,880
>exercício, como posso agora imprimir o valor
em n referindo-me a ele por meio de p?

415
00:22:02,880 --> 00:22:05,910
>O que devo digitar literalmente
como o segundo argumento de printf

416
00:22:05,910 --> 00:22:12,530
>para imprimir o valor de n usando esta
nova variável, p, de alguma forma.

417
00:22:12,530 --> 00:22:16,290
>Sim, vamos chamar Joshua.

418
00:22:16,290 --> 00:22:19,860
>PÚBLICO: Eu acredito, se você
usar o & antes do p,

419
00:22:19,860 --> 00:22:21,642
>provavelmente fará isso.

420
00:22:21,642 --> 00:22:24,100
>DAVID MALAN: OK, & p,
agora eu vou tentar isso.

421
00:22:24,100 --> 00:22:27,700
>Vamos tentar & p
para imprimir esse valor.

422
00:22:27,700 --> 00:22:30,370
>Portanto, & p,
salvarei o arquivo.

423
00:22:30,370 --> 00:22:32,610
>Vou make address e entrar.

424
00:22:32,610 --> 00:22:34,415
>E não parece ser o caso.
425
00:22:34,415 --> 00:22:35,790
>Observe que estou recebendo um erro.

426
00:22:35,790 --> 00:22:36,720
>É um pouco enigmático.

427
00:22:36,720 --> 00:22:40,920
>O formato especifica o tipo int, mas o
argumento tem o tipo int asterisco asterisco,

428
00:22:40,920 --> 00:22:42,090
>Mais disso em outro momento.

429
00:22:42,090 --> 00:22:43,570
>Acontece que isso estava incorreto.

430
00:22:43,570 --> 00:22:47,430
>Vamos dar uma outra sugestão,
porque o &, lembre-se,

431
00:22:47,430 --> 00:22:49,170
>obtém o endereço de algo.

432
00:22:49,170 --> 00:22:50,880
>Mas p já é um endereço.

433
00:22:50,880 --> 00:22:52,590
>Joshua, o que você
propôs tecnicamente,

434
00:22:52,590 --> 00:22:54,300
>foi me dar o endereço do endereço.

435
00:22:54,300 --> 00:22:56,190
>E essa não é a direção
que queremos ir.

436
00:22:56,190 --> 00:22:58,170
>Queremos ir para o que
está naquele endereço.

437
00:22:58,170 --> 00:23:00,740
>Sofia, o que você acha?

438
00:23:00,740 --> 00:23:02,640
>PÚBLICO: Queremos adicionar um % -

439
00:23:02,640 --> 00:23:06,820
>ou um asterisco p quando o imprimimos.

440
00:23:06,820 --> 00:23:07,570
>DAVID MALAN: Sim.

441
00:23:07,570 --> 00:23:09,380
>Então eu tive um pouco de dificuldade em ouvir você.

442
00:23:09,380 --> 00:23:12,370
>Mas acho que, se não usarmos
o operador &,

443
00:23:12,370 --> 00:23:14,710
>mas o operador asterisco,
isso vai ser,

444
00:23:14,710 --> 00:23:17,170
>na verdade, o operador de desreferência,
o que significa ,

445
00:23:17,170 --> 00:23:19,120
>vá para o valor em p.

446
00:23:19,120 --> 00:23:23,530
>E se o valor em p for um endereço,
eu acho, vamos tentar fazer isso, make address.

447
00:23:23,530 --> 00:23:25,490
>Sim, isso compilou OK desta vez.

448
00:23:25,490 --> 00:23:27,550
>Agora, se eu fizer um ponto e
barra de endereço, espero que eu

449
00:23:27,550 --> 00:23:30,400
>veja agora o número 50.

450
00:23:30,400 --> 00:23:33,010
>Portanto, novamente, não parecemos ter
feito nenhum progresso fundamental.

451
00:23:33,010 --> 00:23:36,070
>no fim das contas, ainda estou
imprimindo o valor de n.

452
00:23:36,070 --> 00:23:39,100
>Mas apresentamos este novo primitivo,
esta nova peça do quebra-cabeça,

453
00:23:39,100 --> 00:23:41,440
>se assim preferir, isso permite
que você, programaticamente,

454
00:23:41,440 --> 00:23:44,390
>descubra o endereço de algo
na memória do computador

455
00:23:44,390 --> 00:23:46,540
>e vá para esse endereço.

456
00:23:46,540 --> 00:23:52,070
>E logo vamos exercitar um controle
mais sofisticado.

457
00:23:52,070 --> 00:23:56,050
>Mas vamos voltar a uma
representação disto

458
00:23:56,050 --> 00:23:59,290
>e considere o que acabamos de fazer
no contexto, agora, deste código.

459
00:23:59,290 --> 00:24:02,080
>Então, dentro do meu main, as
duas linhas interessantes de código,

460
00:24:02,080 --> 00:24:05,320
>essas duas linhas eram as
primeiras, antes de adicionarmos

461
00:24:05,320 --> 00:24:07,990
>a sugestão da Sofia, desreferenciando
p e imprimindo com printf.

462
00:24:07,990 --> 00:24:10,810
>Mas vamos considerar, por um momento,
quais são esses valores agora

463
00:24:10,810 --> 00:24:12,280
>que parecem na memória de um computador.

464
00:24:12,280 --> 00:24:14,440
>E, novamente, a sintaxe
é um pouco enigmática

465
00:24:14,440 --> 00:24:16,475
>porque agora temos uma
asterisco e um &.

466
00:24:16,475 --> 00:24:18,850
>Mas, novamente, isso significa apenas,
agora, vamos começar a pensar

467
00:24:18,850 --> 00:24:20,405
>em termos de memória do computador.

468
00:24:20,405 --> 00:24:23,030
>Por exemplo, aqui está uma grade de
memória dentro do meu computador.

469
00:24:23,030 --> 00:24:26,980
>E talvez, por exemplo, o
50 e o n acabam lá embaixo.

470
00:24:26,980 --> 00:24:29,980
>Eles podem acabar em qualquer lugar,
nem mesmo retratados na tela aqui.

471
00:24:29,980 --> 00:24:34,090
>Eles acabam em algum lugar na memória do
computador, para nossos propósitos até agora.

472
00:24:34,090 --> 00:24:36,100
>Mas tecnicamente estão em um endereço.

473
00:24:36,100 --> 00:24:38,950
>E deixe-me simplificar o endereço
para que seja mais rápido de dizer.

474
00:24:38,950 --> 00:24:42,310
>Este 50, agora, armazenado na
variável n, talvez ele

475
00:24:42,310 --> 00:24:44,590
>esteja no endereço 0x123.
476
00:24:44,590 --> 00:24:46,480
>Não tenho ideia de onde
está, mas claramente

477
00:24:46,480 --> 00:24:50,200
>visto que ele pode estar em um endereço
aparentemente aleatório como aquele.

478
00:24:50,200 --> 00:24:51,640
>Agora, que tal p?

479
00:24:51,640 --> 00:24:54,520
>p é tecnicamente uma variável em si.

480
00:24:54,520 --> 00:24:57,190
>É uma variável que armazena
o endereço de outra coisa.

481
00:24:57,190 --> 00:25:00,190
>Mas ainda é uma variável,
o que significa que, quando você declara p

482
00:25:00,190 --> 00:25:04,660
>com o código anterior, ele
ocupa alguns bytes de memória

483
00:25:04,660 --> 00:25:05,660
>na tela.

484
00:25:05,660 --> 00:25:10,420
>E então agora eu vou
propor que p acabe na memória aqui.

485
00:25:10,420 --> 00:25:13,450
>Agora, p é deliberadamente desenhado
para ser mais longo aqui.

486
00:25:13,450 --> 00:25:15,700
>Estou consumindo oito
bytes no total desta vez,

487
00:25:15,700 --> 00:25:20,470
>porque, ao que parece, em sistemas de
computador modernos, incluindo CS50 IDE,

488
00:25:20,470 --> 00:25:23,500
>os ponteiros tendem a ocupar oito bytes.

489
00:25:23,500 --> 00:25:27,190
>Portanto, não um, não quatro, mas oito bytes,
então eu simplesmente desenhei para ser maior.

490
00:25:27,190 --> 00:25:31,240
>Então, o que é
armazenado na variável p?

491
00:25:31,240 --> 00:25:35,600
>Bem, acontece que, novamente, está apenas
armazenando o endereço de algum valor.

492
00:25:35,600 --> 00:25:42,460
>Portanto, se o inteiro n, que por si só está
armazenando 50, estiver na localização 0x123,

493
00:25:42,460 --> 00:25:47,080
>e o ponteiro p está sendo atribuído
a esse endereço, é como dizer,

494
00:25:47,080 --> 00:25:50,620
>bem, armazenado nesta variável p,
é literalmente apenas um número

495
00:25:50,620 --> 00:25:54,190
>representado aqui em notação
hexadecimal, 0x123.

496
00:25:54,190 --> 00:25:56,650
>Então isso é tudo o que está acontecendo
dentro da memória do computador

497
00:25:56,650 --> 00:25:57,858
>com essas duas linhas de código.

498
00:25:57,858 --> 00:26:00,040
>Não há nada fundamentalmente
novo, exceto o fato

499
00:26:00,040 --> 00:26:04,430
>que temos uma nova sintaxe para nos
referirmos a esses endereços explicitamente.

500
00:26:04,430 --> 00:26:06,100
>Este é o n aqui embaixo.
501
00:26:06,100 --> 00:26:07,720
>Este é o p aqui em cima.

502
00:26:07,720 --> 00:26:12,160
>E o valor de p simplesmente
é um endereço.

503
00:26:12,160 --> 00:26:15,205
>Agora, eu continuo dizendo que esses
endereços são um pouco enigmáticos.

504
00:26:15,205 --> 00:26:16,330
>Eles são um pouco arbitrários.

505
00:26:16,330 --> 00:26:16,872
>E são.

506
00:26:16,872 --> 00:26:20,530
>E honestamente, raramente, ou nunca,
vai ser esclarecedor saber,

507
00:26:20,530 --> 00:26:25,030
>como um humano, em que endereço
este inteiro n está.

508
00:26:25,030 --> 00:26:28,550
>Quem se importa se está em 0x123 ou 0x456?

509
00:26:28,550 --> 00:26:29,800
>Geralmente, não.

510
00:26:29,800 --> 00:26:33,070
>E então os cientistas da computação, ao
falar sobre a memória dos computadores,

511
00:26:33,070 --> 00:26:38,010
>tendem a não falar nesses detalhes de baixo
nível, em termos de números reais.

512
00:26:38,010 --> 00:26:40,600
>Em vez disso, eles tendem
a simplificar a imagem,

513
00:26:40,600 --> 00:26:44,230
>tipo de abstração de todas as outras
memórias, o que francamente, não é

514
00:26:44,230 --> 00:26:46,690
>relevante para a discussão
até agora, e apenas

515
00:26:46,690 --> 00:26:50,290
>quer saber, eu sei que p
está armazenando um endereço.

516
00:26:50,290 --> 00:26:53,740
>E esse endereço é o
de 50 aqui embaixo.

517
00:26:53,740 --> 00:26:56,830
>Mas eu não me importo, na
minha vida diária de programação,

518
00:26:56,830 --> 00:26:58,360
>quais são esses endereços específicos.

519
00:26:58,360 --> 00:26:59,230
>E sabe do que mais?

520
00:26:59,230 --> 00:27:01,730
>Vamos abstrair isso rapidamente.

521
00:27:01,730 --> 00:27:06,250
>E, novamente, abstração é simplificar
os detalhes de nível inferior

522
00:27:06,250 --> 00:27:09,250
>que você pode muito bem precisar
entender, mas não necessariamente

523
00:27:09,250 --> 00:27:10,520
>precisa continuar pensando.

524
00:27:10,520 --> 00:27:11,950
>Você não precisa ficar
pensando neste nível.

525
00:27:11,950 --> 00:27:13,730
>Basta pensar neste nível.

526
00:27:13,730 --> 00:27:16,600
>Então, podemos também desenhar
um ponteiro,

527
00:27:16,600 --> 00:27:20,710
>como apontando para algum valor
e independentemente de qual

528
00:27:20,710 --> 00:27:22,330
>o endereço real é.

529
00:27:22,330 --> 00:27:25,150
>E esse é o caso em
nosso mundo humano.

530
00:27:25,150 --> 00:27:29,200
>Temos convenções muito
semelhantes,

531
00:27:29,200 --> 00:27:31,750
>seja ou não óbvio à
primeira vista, tal

532
00:27:31,750 --> 00:27:37,310
>que podemos muito bem estar usando esses
mesmos mecanismos em nossa vida cotidiana.

533
00:27:37,310 --> 00:27:40,690
>Por exemplo, se acontecer de você ter
uma caixa de correio na rua de sua casa

534
00:27:40,690 --> 00:27:43,768
>ou no porão de Harvard, no
Centro de Ciências,

535
00:27:43,768 --> 00:27:46,810
>pode muito bem se parecer com algo
assim, pelo menos mais residencial.

536
00:27:46,810 --> 00:27:51,100
>E suponha que esta caixa de correio aqui
esteja representando, neste caso, p,

537
00:27:51,100 --> 00:27:51,790
>nessa história.

538
00:27:51,790 --> 00:27:55,490
>É armazenar um ponteiro, ou seja,
o endereço de outra coisa.

539
00:27:55,490 --> 00:27:58,360
>Bem, se houver um monte de
outras caixas de correio na rua,

540
00:27:58,360 --> 00:28:01,510
>bem, podemos colocar o que quisermos
nessas caixas de correio.

541
00:28:01,510 --> 00:28:04,840
>Podemos colocar cartões postais,
cartas, até pacotes.

542
00:28:04,840 --> 00:28:08,250
>E assim como no mundo real,
podemos fazer o mesmo no virtual.

543
00:28:08,250 --> 00:28:12,890
>Posso armazenar caracteres ou inteiros
ou outras coisas, incluindo endereços.

544
00:28:12,890 --> 00:28:17,100
>Brian, por exemplo, acho que você tem sua
própria caixa de correio em outro lugar.

545
00:28:17,100 --> 00:28:20,660
>E Brian, é claro, tem uma caixa de
correio que tem um endereço exclusivo.

546
00:28:20,660 --> 00:28:23,600
>Brian, por exemplo, o
que é o endereço único

547
00:28:23,600 --> 00:28:26,030
>da caixa de correio da sua rua aí?

548
00:28:26,030 --> 00:28:27,600
>BRIAN: Sim, então aqui está minha caixa de correio.

549
00:28:27,600 --> 00:28:28,370
>É rotulada como n.

550
00:28:28,370 --> 00:28:29,750
>E seu endereço está aqui.

551
00:28:29,750 --> 00:28:33,200
>O endereço da minha caixa de
correio parece ser 0x123.

552
00:28:33,200 --> 00:28:35,450
>DAVID MALAN: Sim, minha caixa de
correio também tem um endereço.

553
00:28:35,450 --> 00:28:37,200
>Francamente, novamente, eu
não me importo com isso.

554
00:28:37,200 --> 00:28:39,033
>Então eu nem mesmo coloquei
na caixa de correio aqui.

555
00:28:39,033 --> 00:28:43,070
>Mas se minha caixa de correio representa p,
um ponteiro e a caixa de correio de Brian

556
00:28:43,070 --> 00:28:45,920
>representa n, um
inteiro, bem, deveria

557
00:28:45,920 --> 00:28:49,260
>significa que se eu olhar dentro
do conteúdo do meu ponteiro

558
00:28:49,260 --> 00:28:53,690
>e vejo o valor 0x123,
essa agora é minha pista,

559
00:28:53,690 --> 00:28:57,560
>uma espécie de migalha de pão, que agora me permite
dar uma olhada na caixa de correio de Brian.

560
00:28:57,560 --> 00:29:00,320
>E Brian, se você não se
importasse de fazer isso por nós,

561
00:29:00,320 --> 00:29:02,430
>o que você tem nesse endereço?

562
00:29:02,430 --> 00:29:05,540
>BRIAN: E se eu olhar em minha caixa
de correio no endereço 0x123,

563
00:29:05,540 --> 00:29:07,727
>Tenho o número 50 dentro
desta caixa de correio.

564
00:29:07,727 --> 00:29:08,810
>DAVID MALAN: Sim.

565
00:29:08,810 --> 00:29:10,400
>Portanto, neste caso, ele
está armazenando um int.

566
00:29:10,400 --> 00:29:11,650
>Mas pode ser qualquer outra coisa.

567
00:29:11,650 --> 00:29:14,480
>E, novamente, normalmente não nos
importamos com esses endereços específicos.

568
00:29:14,480 --> 00:29:17,450
>Depois de entender a metáfora,
podemos fazer algo bobo

569
00:29:17,450 --> 00:29:20,630
>e pensar nessa caixa de correio
como armazenando um valor que está

570
00:29:20,630 --> 00:29:23,180
>apontando para a caixa de correio de Brian.

571
00:29:23,180 --> 00:29:26,510
>É algum tipo de direção desenhada
lá, como uma seta,

572
00:29:26,510 --> 00:29:29,000
>aqui como um dedo de espuma bobo.

573
00:29:29,000 --> 00:29:34,750
>Ou, se preferir, um dedo da Yale, feito de espuma,
apontando para a caixa de correio de Brian,

574
00:29:34,750 --> 00:29:38,720
>apenas como uma espécie de trilha de navegação
que nos leva a algum outro valor na tela.

575
00:29:38,720 --> 00:29:41,408
>Então, quando falamos hoje
e além sobre endereços,
576
00:29:41,408 --> 00:29:42,700
>é nisso que falamos.

577
00:29:42,700 --> 00:29:45,790
>Nós, humanos, no mundo real, temos
usado endereços por eras, agora,

578
00:29:45,790 --> 00:29:49,030
>para identificar com exclusividade
nossas casas ou empresas ou semelhantes.

579
00:29:49,030 --> 00:29:51,520
>Os computadores fazem exatamente a
mesma coisa em um nível inferior

580
00:29:51,520 --> 00:29:53,440
>usando a memória do computador.

581
00:29:53,440 --> 00:29:58,330
>Vou fazer uma pausa aqui para ver se
há alguma dúvida sobre ponteiros, variáveis

582
00:29:58,330 --> 00:30:00,760
>que armazenam endereços, ou
nessas novos operadores,

583
00:30:00,760 --> 00:30:02,890
>como o & ou o asterisco, que

584
00:30:02,890 --> 00:30:06,310
>agora tem um novo significado.

585
00:30:06,310 --> 00:30:06,968
>Nada ainda.

586
00:30:06,968 --> 00:30:09,010
>Tudo bem, vamos considerar agora,

587
00:30:09,010 --> 00:30:12,250
>a mesma história no contexto de um
tipo de dados completamente diferente.

588
00:30:12,250 --> 00:30:15,310
>Até agora, jogamos apenas com ints.
589
00:30:15,310 --> 00:30:16,630
>Mas considere strings.

590
00:30:16,630 --> 00:30:20,950
>Gastamos muito tempo com strings,
usando criptografia com elas

591
00:30:20,950 --> 00:30:25,880
>e resolvendo a implementação de algoritmos
eleitorais usando a entrada do usuário.

592
00:30:25,880 --> 00:30:27,940
>Então, vamos considerar um dado
fundamentalmente diferente

593
00:30:27,940 --> 00:30:31,940
>que armazena, não inteiros individuais,
mas strings de texto.

594
00:30:31,940 --> 00:30:34,150
>Então, por exemplo, em qualquer
programa envolvendo uma string,

595
00:30:34,150 --> 00:30:38,245
>você pode ter uma linha de código semelhante
a esta. string s é igual a, aspas

596
00:30:38,245 --> 00:30:40,090
>"HI!"

597
00:30:40,090 --> 00:30:41,852
>em maiúsculas com um ponto de exclamação.

598
00:30:41,852 --> 00:30:44,560
>Portanto, essa pode muito bem ser uma
linha de código que vimos até agora.

599
00:30:44,560 --> 00:30:46,935
>O que está acontecendo
dentro da memória do computador?

600
00:30:46,935 --> 00:30:51,340
>Bem, deixe-me sugerir que, quando você digitar
"HI!" em um computador,

601
00:30:51,340 --> 00:30:53,780
>ele acaba em algum lugar na
memória do seu computador.

602
00:30:53,780 --> 00:30:58,840
>Então, HI!, mais, como vimos semana
passada, uma \ 0-- ou duas semanas atrás,

603
00:30:58,840 --> 00:31:04,040
>uma \ 0, que é como um
computador representa o final dessa string.

604
00:31:04,040 --> 00:31:06,100
>Mas vamos olhar um pouco
mais cuidadosamente

605
00:31:06,100 --> 00:31:08,350
>o que está acontecendo
debaixo deste capô aqui.

606
00:31:08,350 --> 00:31:12,190
>Tecnicamente falando, eu poderia
abordar esses caracteres individuais

607
00:31:12,190 --> 00:31:16,280
>como vimos a partir da segunda semana, usando a
notação de colchetes como o colchete 0,

608
00:31:16,280 --> 00:31:18,910
>s colchete 1, s colchete 2 e
s colchete 3

609
00:31:18,910 --> 00:31:22,427
>Usamos a notação de colchetes
para tratar uma string

610
00:31:22,427 --> 00:31:24,010
>como se fosse um array de caracteres.

611
00:31:24,010 --> 00:31:26,900
>E é, foi e ainda é.

612
00:31:26,900 --> 00:31:32,230
>Mas acontece que as strings também podem
ser manipuladas por meio de seus endereços

613
00:31:32,230 --> 00:31:32,960
>também.
614
00:31:32,960 --> 00:31:36,640
>E então, por exemplo, talvez
esta mesma string exata, HI,

615
00:31:36,640 --> 00:31:43,480
>armazenada no endereço de memória
0x123 e então 0x124, 0x125 e 0x126.

616
00:31:43,480 --> 00:31:46,150
>Observe que são
deliberadamente contíguos

617
00:31:46,150 --> 00:31:47,560
>os endereços, de ponta a ponta.

618
00:31:47,560 --> 00:31:50,870
>E estão separados por apenas um byte,
porque cada um desses chars, é claro,

619
00:31:50,870 --> 00:31:53,140
>são apenas um byte em C.

620
00:31:53,140 --> 00:31:56,920
>Portanto, esses números não são
importantes, especificamente.

621
00:31:56,920 --> 00:31:59,530
>Mas o fato de eles estarem
separados um do outro

622
00:31:59,530 --> 00:32:02,350
>é importante, porque essa é
a definição de uma string,

623
00:32:02,350 --> 00:32:05,470
>e, um array,
ter memória consecutiva.

624
00:32:05,470 --> 00:32:08,140
>Agora, o que exatamente é S?

625
00:32:08,140 --> 00:32:11,530
>S era o nome da variável que dei um momento
atrás para ir para essa linha de código,

626
00:32:11,530 --> 00:32:13,840
>string S igual "HI."

627
00:32:13,840 --> 00:32:14,710
>bem, o que é S?

628
00:32:14,710 --> 00:32:18,950
>S é uma variável que precisa ir para
algum lugar na memória do computador.

629
00:32:18,950 --> 00:32:24,880
>E suponha que S seja,
HI com um ponto de exclamação.

630
00:32:24,880 --> 00:32:28,600
>E acontece que o HI
fica neste local aqui.

631
00:32:28,600 --> 00:32:31,390
>Você sabe o que você pode
pensar de S como sendo agora,

632
00:32:31,390 --> 00:32:34,840
>não é, em um nível alto, uma
string, mas em um nível inferior,

633
00:32:34,840 --> 00:32:37,300
>é o endereço de uma string.

634
00:32:37,300 --> 00:32:40,780
>Mais especificamente, vamos
começar a pensar em uma string

635
00:32:40,780 --> 00:32:46,297
>como sendo tecnicamente apenas o endereço
do primeiro caractere na string.

636
00:32:46,297 --> 00:32:48,130
>Agora, isso pode fazer
você parar por um momento,

637
00:32:48,130 --> 00:32:49,810
>por que o primeiro caractere?

638
00:32:49,810 --> 00:32:53,710
>Como você vai se lembrar disso, espere um
minuto, esta string não está apenas
639
00:32:53,710 --> 00:32:54,940
>em 0x123.

640
00:32:54,940 --> 00:33:00,110
>Também continua em
0x124, 0x125 e assim por diante.

641
00:33:00,110 --> 00:33:02,950
>Mas deixe-me fazer uma pausa e
perguntar ao grupo aqui, por que

642
00:33:02,950 --> 00:33:06,110
>pode muito bem ser suficiente
para um computador

643
00:33:06,110 --> 00:33:12,550
>e nós, programadores, pensemos
apenas em strings em termos de ser

644
00:33:12,550 --> 00:33:15,460
>o endereço do primeiro byte.

645
00:33:15,460 --> 00:33:18,220
>Tipo, por que é suficiente,
não importa quanto tempo

646
00:33:18,220 --> 00:33:20,830
>a string é, mesmo que seja um
parágrafo inteiro de texto,

647
00:33:20,830 --> 00:33:25,360
>por que é muito habilmente suficiente
pensar em uma string como S

648
00:33:25,360 --> 00:33:31,420
>como sendo idêntica ao
endereço do primeiro byte?

649
00:33:31,420 --> 00:33:33,718
>Ginni, não é?

650
00:33:33,718 --> 00:33:37,480
>PÚBLICO: Possivelmente porque acontece que
as strings, sempre que estamos definindo

651
00:33:37,480 --> 00:33:39,490
>uma nova string, isso é tudo.

652
00:33:39,490 --> 00:33:44,410
>Suponha que, se estou escrevendo meu nome, Ginni,
então será G-I-N-N-I.

653
00:33:44,410 --> 00:33:46,810
>Portanto, será suficiente
se algo for apontado

654
00:33:46,810 --> 00:33:50,560
>para apenas o primeiro caractere do
meu nome, para que eu possa apenas

655
00:33:50,560 --> 00:33:55,895
>seguir para o primeiro caractere e, em
seguida, obter todos os caracteres.

656
00:33:55,895 --> 00:33:56,770
>DAVID MALAN: Perfeito.

657
00:33:56,770 --> 00:33:59,800
>Todas essas definições básicas
que tivemos nas últimas semanas

658
00:33:59,800 --> 00:34:00,790
>agora se juntaram.

659
00:34:00,790 --> 00:34:02,812
>Se uma string é um
array de caracteres -

660
00:34:02,812 --> 00:34:05,020
>e por definição de array,
esses caracteres estão

661
00:34:05,020 --> 00:34:09,280
>de ponta a ponta e, duas semanas atrás, cada string

662
00:34:09,280 --> 00:34:13,300
>termina com este caractere de barra
invertida convencional zero ou nulo.

663
00:34:13,300 --> 00:34:15,550
>Tudo o que você precisa fazer
ao pensar em uma string
664
00:34:15,550 --> 00:34:17,530
>é saber onde
a string começa,

665
00:34:17,530 --> 00:34:19,719
>porque você pode usar um
loop for ou um loop while

666
00:34:19,719 --> 00:34:22,540
>ou alguma outra heurística com uma
condição e uma expressão booleana

667
00:34:22,540 --> 00:34:25,929
>para descobrir onde a string
termina, mesmo sem saber,

668
00:34:25,929 --> 00:34:27,710
>antecipadamente, seu comprimento.

669
00:34:27,710 --> 00:34:30,159
>Quer dizer, vamos
começar, por enquanto,

670
00:34:30,159 --> 00:34:32,679
>pensando em strings como
sendo simplesmente

671
00:34:32,679 --> 00:34:37,969
>apenas o endereço do
primeiro caractere na string.

672
00:34:37,969 --> 00:34:40,989
>E se tomarmos isso como um
fato, vamos em frente, agora,

673
00:34:40,989 --> 00:34:43,989
>e começar a brincar com um programa que não
usa números inteiros, mas em vez disso,

674
00:34:43,989 --> 00:34:46,570
>strings usadas, usando
este primitivo básico.

675
00:34:46,570 --> 00:34:49,929
>Então, agora eu vou deletar o
código que escrevi antes, um adddress.c.
676
00:34:49,929 --> 00:34:54,580
>Vou mudar para uma string igual a
ponto-e-vírgula "HI".

677
00:34:54,580 --> 00:34:57,700
>E observe, eu não estou digitando
manualmente nenhum 0 de \.

678
00:34:57,700 --> 00:34:59,560
>C faz isso para nós automaticamente.

679
00:34:59,560 --> 00:35:02,260
>Quando você fecha a aspas,
o compilador cuida

680
00:35:02,260 --> 00:35:04,158
>de adicionar a \ 0 para você.

681
00:35:04,158 --> 00:35:05,950
>Agora, vou em frente
na próxima linha

682
00:35:05,950 --> 00:35:10,042
>e imprima %
s \ vírgula s,

683
00:35:10,042 --> 00:35:11,500
>se eu quiser imprimir essa string.

684
00:35:11,500 --> 00:35:13,968
>Agora, este programa não
é mais interessante.

685
00:35:13,968 --> 00:35:15,760
>Na primeira semana,
escrevemos algo como -

686
00:35:15,760 --> 00:35:18,730
>OK, sim, é interessante
porque eu estraguei tudo.

687
00:35:18,730 --> 00:35:19,780
>Então, cinco erros.

688
00:35:19,780 --> 00:35:22,450
>Escrevi sete linhas de
código e cinco erros.

689
00:35:22,450 --> 00:35:24,070
>E vamos ver o que está acontecendo.

690
00:35:24,070 --> 00:35:27,430
>Como sempre, vá sempre para o topo,
porque as probabilidades são,

691
00:35:27,430 --> 00:35:29,650
>de haver um efeito
em cascata confuso.

692
00:35:29,650 --> 00:35:34,090
>O primeiro erro que vejo é o uso de
string de identificador não declarado.

693
00:35:34,090 --> 00:35:35,230
>Eu quis dizer padrão n?

694
00:35:35,230 --> 00:35:37,900
>Eu não quis dizer padrão n,
string, string, string.

695
00:35:37,900 --> 00:35:40,780
>Então, eu poderia rodar help50 como
minha fronteira, mas, honestamente, eu

696
00:35:40,780 --> 00:35:43,150
>cometo esse erro com frequência
suficiente para que eu saiba agora

697
00:35:43,150 --> 00:35:46,690
>que esqueci de incluir cs50.h.

698
00:35:46,690 --> 00:35:49,960
>E, se eu fizer isso
e recompilar make address -

699
00:35:49,960 --> 00:35:53,080
>OK, todos os cinco erros são eliminados
apenas por aquela mudança simples.

700
00:35:53,080 --> 00:35:56,200
>E se eu executar o endereço agora,
ele simplesmente vai dizer HI.
701
00:35:56,200 --> 00:35:59,020
>Mas agora vamos começar a
considerar o que está acontecendo

702
00:35:59,020 --> 00:36:00,650
>por baixo do capô deste programa.

703
00:36:00,650 --> 00:36:06,040
>Suponha que eu esteja curioso e
queira imprimir o que é

704
00:36:06,040 --> 00:36:08,170
>o endereço em que esta string reside.

705
00:36:08,170 --> 00:36:09,520
>Bem, acontece -

706
00:36:09,520 --> 00:36:10,690
>deixe-me ser inteligente aqui.

707
00:36:10,690 --> 00:36:14,830
>Vamos imprimir, não um código de
% s, mas % p.

708
00:36:14,830 --> 00:36:18,290
>Mostre-me esta mesma string como um endereço.

709
00:36:18,290 --> 00:36:22,060
>Eu vou recompilar,
make address, parece compilar OK.

710
00:36:22,060 --> 00:36:23,560
>Vamos executar
./ address.

711
00:36:23,560 --> 00:36:26,350
>E novamente, ainda estou imprimindo
s, mas estou pedindo printf

712
00:36:26,350 --> 00:36:30,260
>para apresentá-lo como se fosse um ponteiro.

713
00:36:30,260 --> 00:36:32,430
>E interessante, não
é o mesmo de antes.
714
00:36:32,430 --> 00:36:35,060
>Mas, novamente, isso é razoável
porque os endereços de memória

715
00:36:35,060 --> 00:36:36,540
>não serão sempre os mesmos.

716
00:36:36,540 --> 00:36:37,940
>Mas não importa o que seja.

717
00:36:37,940 --> 00:36:39,232
>Mas isso é interessante.

718
00:36:39,232 --> 00:36:41,750
>Todo esse tempo, sempre que
você estiver usando strings,

719
00:36:41,750 --> 00:36:44,300
>você tinha acabado de mudar seu
%s para % p,

720
00:36:44,300 --> 00:36:48,290
>você poderia ter visto onde, na
memória, essa string começa.

721
00:36:48,290 --> 00:36:50,780
>Ainda não é funcionalmente
útil para nós.

722
00:36:50,780 --> 00:36:52,700
>Mas está lá o tempo todo.

723
00:36:52,700 --> 00:36:54,800
>Agora eu vou
fazer o seguinte.

724
00:36:54,800 --> 00:36:58,950
>Suponha que eu fique um pouco
mais curioso e faça printf.

725
00:36:58,950 --> 00:37:02,390
>Eu vou imprimir outro
endereço seguido por uma nova linha.

726
00:37:02,390 --> 00:37:07,035
>Agora eu vou imprimir
o endereço do primeiro caractere.

727
00:37:07,035 --> 00:37:08,660
>Então, novamente, isso é um pouco estranho de se fazer.

728
00:37:08,660 --> 00:37:10,220
>E normalmente não faríamos
isso com tanta frequência.

729
00:37:10,220 --> 00:37:13,430
>Mas, novamente, apenas para deixar claro que
esses operadores nos fornecem muito simples

730
00:37:13,430 --> 00:37:16,850
>respostas a perguntas como,
qual é o endereço dessa coisa?

731
00:37:16,850 --> 00:37:23,960
>Se s colchete i, a partir da segunda semana em CS50,
representou o segundo caractere em s,

732
00:37:23,960 --> 00:37:28,190
>porque o índice 0 significa s colchete 0
é o primeiro, s colchete 1 é o segundo.

733
00:37:28,190 --> 00:37:30,410
>Se eu brincar com o
novo operador de hoje,

734
00:37:30,410 --> 00:37:36,020
>este &, aposto que posso ver
o endereço desse segundo caractere.

735
00:37:36,020 --> 00:37:38,390
>E, deixe-me ir em
frente e ser mais explícito.

736
00:37:38,390 --> 00:37:43,160
>Vou mudar este primeiro s para o
colchete 0 e colocar um & aqui.

737
00:37:43,160 --> 00:37:46,430
>E deixe-me ir em frente, agora, e
fazer este programa, make address.

738
00:37:46,430 --> 00:37:48,170
>OK, um pouco esquisito -

739
00:37:48,170 --> 00:37:49,680
>Acabei de perder um ponto e vírgula.

740
00:37:49,680 --> 00:37:51,060
>Tão fácil consertar.

741
00:37:51,060 --> 00:37:53,600
>Vamos prosseguir e
recompilar com make address.

742
00:37:53,600 --> 00:37:55,880
>Vamos prosseguir e executar
./ endereço.

743
00:37:55,880 --> 00:37:58,970
>E interessante, bem, talvez -

744
00:37:58,970 --> 00:38:00,320
>interessante para mim.

745
00:38:00,320 --> 00:38:02,780
>Então você vê, agora, dois
endereços, o primeiro dos quais

746
00:38:02,780 --> 00:38:08,900
>é 0x4006a4, que aparentemente é o
endereço do primeiro caractere em s.

747
00:38:08,900 --> 00:38:10,880
>Mas observe o que há
de curioso no próximo.

748
00:38:10,880 --> 00:38:15,720
>É quase o mesmo, exceto que o
byte está um mais distante.

749
00:38:15,720 --> 00:38:18,380
>E eu aposto que se eu fizer
isso, não apenas para "h" e "i",

750
00:38:18,380 --> 00:38:20,330
>mas também o ponto de
exclamação - deixe-me fazer

751
00:38:20,330 --> 00:38:23,210
>mais uma linha de código
quase idêntica, apenas

752
00:38:23,210 --> 00:38:26,240
>para deixar claro que todo
esse tempo é,

753
00:38:26,240 --> 00:38:30,560
>é o caso em que todos os caracteres
em uma string estão consecutivos.

754
00:38:30,560 --> 00:38:32,540
>E agora você pode vê-lo em código.

755
00:38:32,540 --> 00:38:37,610
>b4, b5, b6 estão separados por apenas um byte.

756
00:38:37,610 --> 00:38:40,940
>Então, vemos alguma confirmação visual,
agora, essas strings são de fato

757
00:38:40,940 --> 00:38:42,990
>colocadas na memória assim.

758
00:38:42,990 --> 00:38:46,130
>Agora, novamente, este não é um
exercício programático muito útil

759
00:38:46,130 --> 00:38:48,500
>ver o endereço de
caracteres individuais.

760
00:38:48,500 --> 00:38:51,350
>Mas, novamente, isso é para
enfatizar que, por baixo do capô,

761
00:38:51,350 --> 00:38:53,960
>algumas operações relativamente
simples estão sendo

762
00:38:53,960 --> 00:38:58,562
>habilitadas por meio deste novo &,
e por sua vez, operador asterisco.

763
00:38:58,562 --> 00:39:00,770
>Então, vamos considerar por um
momento o que isso parece

764
00:39:00,770 --> 00:39:02,390
>dentro da memória do computador.

765
00:39:02,390 --> 00:39:05,660
>Em um baixo nível, sim, s é
tecnicamente um endereço.

766
00:39:05,660 --> 00:39:08,540
>E sim, é tecnicamente o
endereço do primeiro byte,

767
00:39:08,540 --> 00:39:10,880
>que no computador real,
parecia diferente.

768
00:39:10,880 --> 00:39:13,100
>Mas no meu slide aqui, eu
apenas propus arbitrariamente

769
00:39:13,100 --> 00:39:17,210
>que está em 0x123, 0x124, 0x125.

770
00:39:17,210 --> 00:39:20,300
>Mas, novamente, não vamos nos
importar com esse nível de detalhe.

771
00:39:20,300 --> 00:39:23,210
>Vamos abstrair esses endereços

772
00:39:23,210 --> 00:39:30,950
>e agora comece a pensar em s, que é uma
string, como tecnicamente apenas sendo

773
00:39:30,950 --> 00:39:32,450
>um ponteiro.

774
00:39:32,450 --> 00:39:33,260
>Um ponteiro.

775
00:39:33,260 --> 00:39:36,463
>Acontece que, embora seja
muito útil e muito comum

776
00:39:36,463 --> 00:39:39,380
>pensar em strings como, obviamente,
sendo apenas sequências de caracteres.

777
00:39:39,380 --> 00:39:41,240
>E isso é verdade desde a primeira semana.

778
00:39:41,240 --> 00:39:43,130
>E você também pode pensar
nelas como arrays,

779
00:39:43,130 --> 00:39:44,990
>sequências consecutivas de caracteres.

780
00:39:44,990 --> 00:39:47,330
>Você também pode, ao que
parece, a partir de hoje,

781
00:39:47,330 --> 00:39:51,290
>pensar nelas como apenas
ponteiros, ou seja,

782
00:39:51,290 --> 00:39:54,900
>o endereço de um caractere em algum
lugar na memória do computador.

783
00:39:54,900 --> 00:39:58,550
>E como Ginni observa, porque todos
os caracteres em uma string

784
00:39:58,550 --> 00:40:00,770
>são, por definição,
de ponta a ponta,

785
00:40:00,770 --> 00:40:05,720
>porque, por definição, todas as strings
terminam com uma \ 0, que

786
00:40:05,720 --> 00:40:08,750
>é literalmente a menor e única
quantidade de informação

787
00:40:08,750 --> 00:40:12,920
>que você precisa manter um computador para
saber onde estão todas as suas strings.

788
00:40:12,920 --> 00:40:16,340
>Basta lembrar o endereço
do primeiro caractere

789
00:40:16,340 --> 00:40:19,430
>porque você pode encontrar
seu caminho até o fim

790
00:40:19,430 --> 00:40:24,320
>lembrando que esta \ 0 é,
na verdade, apenas oito 0

791
00:40:24,320 --> 00:40:27,080
>bits, representada
como \ 0.

792
00:40:27,080 --> 00:40:29,617
>E então certamente poderíamos
ter uma condição if,

793
00:40:29,617 --> 00:40:31,700
>muito parecida com o que fizemos há
duas semanas, quando brincávamos

794
00:40:31,700 --> 00:40:36,230
>com o comprimento das strings, que nos
permite verificar precisamente isso.

795
00:40:36,230 --> 00:40:41,030
>E então, quando digo que vamos
remover as muletas, aqui está.

796
00:40:41,030 --> 00:40:44,330
>Até agora, estamos usando,
novamente, a biblioteca CS50,

797
00:40:44,330 --> 00:40:47,470
>o que nos dá, convenientemente,
funções como get string e get int

798
00:40:47,470 --> 00:40:49,650
>e get float e assim por diante.

799
00:40:49,650 --> 00:40:54,650
>Mas todo esse tempo, a biblioteca CS50,
especificamente o arquivo, cs50.h,

800
00:40:54,650 --> 00:40:58,070
>teve um pouco de simplificação
pedagógica.

801
00:40:58,070 --> 00:41:02,510
>Lembre-se da semana passada, que você pode definir
seus próprios tipos de dados personalizados.

802
00:41:02,510 --> 00:41:06,955
>Bem, acontece que todo esse tempo,
temos afirmado que existem strings

803
00:41:06,955 --> 00:41:09,080
>e são algo que você
pode usar em seus programas.

804
00:41:09,080 --> 00:41:14,420
>E strings existem em C. Elas existem
em Python, em Java Script, em Java,

805
00:41:14,420 --> 00:41:16,980
>e C, em muitas, muitas, muitas outras linguagens.

806
00:41:16,980 --> 00:41:18,860
>Este não é um termo CS50.

807
00:41:18,860 --> 00:41:25,190
>Mas string, tecnicamente, não existe como
um tipo de dados em C. Em vez disso,

808
00:41:25,190 --> 00:41:31,180
>é mais cripticamente e de nível mais
baixo conhecido como char*.

809
00:41:31,180 --> 00:41:33,080
>Asterisco char,
agora o que isso significa?

810
00:41:33,080 --> 00:41:37,180
>Bem, char*, muito parecida com nosso
asterisco int de alguns minutos atrás,

811
00:41:37,180 --> 00:41:40,840
>apenas representa o endereço de
um caractere, bem como int asterisco

812
00:41:40,840 --> 00:41:43,210
>representa o endereço de um int.
813
00:41:43,210 --> 00:41:46,210
>E se, novamente, você meio
que concorda comigo agora,

814
00:41:46,210 --> 00:41:49,450
>que você pode pensar em strings
como sequências de caracteres,

815
00:41:49,450 --> 00:41:52,660
>ou mais especificamente, arrays de
caracteres ou, mais especificamente,

816
00:41:52,660 --> 00:41:56,920
>a partir de hoje, o endereço
apenas do primeiro caractere,

817
00:41:56,920 --> 00:41:59,680
>então é, o caso
de que agora podemos

818
00:41:59,680 --> 00:42:02,800
>aplicar esta nova terminologia,
hoje, de ponteiro,

819
00:42:02,800 --> 00:42:06,040
>para nossas velhas amigas,
as strings.

820
00:42:06,040 --> 00:42:10,690
>String é a mesma coisa que um sinônimo,
se assim preferir, de char*.

821
00:42:10,690 --> 00:42:14,200
>E é na biblioteca CS50 que
temos uma linha de código

822
00:42:14,200 --> 00:42:18,348
>que simplifica ou abstrai asterisco
char, que honestamente, ninguém quer

823
00:42:18,348 --> 00:42:20,890
>pensar ou ter essa dificuldade na
primeira semana de aula,

824
00:42:20,890 --> 00:42:23,260
>muito menos as primeiras duas
ou três semanas de aula.
825
00:42:23,260 --> 00:42:28,475
>É uma simplificação, um tipo de dado
customizado, que chamamos de string,

826
00:42:28,475 --> 00:42:30,850
>só para você não ter que
pensar, o que é esse asterisco?

827
00:42:30,850 --> 00:42:32,017
>O que isso significa para o caractere?

828
00:42:32,017 --> 00:42:33,100
>Sobre qual é o endereço?

829
00:42:33,100 --> 00:42:37,450
>Mas hoje podemos remover essas rodas de
treinamento e revelar isso, todo esse tempo,

830
00:42:37,450 --> 00:42:40,720
>você manipulou caracteres
em endereços específicos.

831
00:42:40,720 --> 00:42:43,180
>E usamos esse tipo
de técnica antes,

832
00:42:43,180 --> 00:42:45,550
>abstraindo esses detalhes
de nível inferior.

833
00:42:45,550 --> 00:42:48,310
>Por exemplo, lembre-se na semana
passada, que introduzimos

834
00:42:48,310 --> 00:42:52,630
>essa noção de uma estrutura, um tipo de dados
que você pode personalizar.

835
00:42:52,630 --> 00:42:56,200
>Nós implementamos uma melhor
lista telefônica, envolvendo

836
00:42:56,200 --> 00:42:58,630
>um nome e um número dentro de
um tipo de dados personalizado,
837
00:42:58,630 --> 00:43:01,960
>encapsulando-os se assim preferir,
dentro de algo que chamamos de pessoa.

838
00:43:01,960 --> 00:43:05,650
>E toda pessoa que afirmamos
ter uma estrutura

839
00:43:05,650 --> 00:43:07,580
>que contém um nome e um número.

840
00:43:07,580 --> 00:43:11,410
>E pelo caminho dessa característica do C,
typedef, podemos definir um novo tipo.

841
00:43:11,410 --> 00:43:15,200
>E o nome desse na semana passada,
era apenas uma pessoa.

842
00:43:15,200 --> 00:43:18,100
>Então, já estamos usando e
temos estado secretamente

843
00:43:18,100 --> 00:43:22,750
>usando desde a primeira semana do C,
uma linha de código que

844
00:43:22,750 --> 00:43:24,020
>se parece com isso.

845
00:43:24,020 --> 00:43:28,090
>E esta é, uma das linhas
de código dentro de cs50.h.

846
00:43:28,090 --> 00:43:31,000
>Diz typedef, o que significa
me dê um tipo personalizado.

847
00:43:31,000 --> 00:43:35,770
>E cria um sinônimo para
char* chamado string.

848
00:43:35,770 --> 00:43:39,700
>E é uma maneira de
esconder a char*.

849
00:43:39,700 --> 00:43:42,070
>Podemos ocultar o asterisco,
em particular, o que não

850
00:43:42,070 --> 00:43:43,990
>seria divertido de brincar
nos primeiros dias,

851
00:43:43,990 --> 00:43:47,200
>sem alterar a definição
do que é uma string.

852
00:43:47,200 --> 00:43:51,850
>Portanto, strings existem em C. Mas não há
nenhum tipo de dado chamado string em C

853
00:43:51,850 --> 00:43:56,020
>até usar uma biblioteca como
CS50's, que o faz existir

854
00:43:56,020 --> 00:43:58,930
>por meio desse tipo de definição.

855
00:43:58,930 --> 00:44:01,450
>Tudo bem, deixe-me fazer uma
pausa aqui para ver se há

856
00:44:01,450 --> 00:44:03,760
>qualquer dúvida, então,
sobre o que são strings

857
00:44:03,760 --> 00:44:09,360
>ou essas novas formas
de pensar sobre elas.

858
00:44:09,360 --> 00:44:13,390
>Alguma dúvida sobre strings
ou char*s?

859
00:44:13,390 --> 00:44:15,140
>Tudo bem, bem, se não houver
perguntas aqui, por que

860
00:44:15,140 --> 00:44:17,515
>não vamos em frente e fazemos uma
pausa de 5 minutos aqui primeiro.

861
00:44:17,515 --> 00:44:19,790
>E estaremos de volta em 5
e daremos outra olhada

862
00:44:19,790 --> 00:44:22,040
>no que podemos fazer agora
com esses novos primitivos.

863
00:44:22,040 --> 00:44:23,480
>Tudo bem, estamos de volta.

864
00:44:23,480 --> 00:44:27,680
>E temos, agora, essa capacidade no código
de obter o endereço de alguma variável

865
00:44:27,680 --> 00:44:30,140
>e também para ir a um
endereço usando &

866
00:44:30,140 --> 00:44:31,850
>e o asterisco, respectivamente.

867
00:44:31,850 --> 00:44:36,530
>Nós pensamos em strings como sendo
não apenas sequências contíguas

868
00:44:36,530 --> 00:44:38,150
>de caracteres, mas também arrays.

869
00:44:38,150 --> 00:44:42,477
>E então, é claro, a partir
de hoje, endereços reais,

870
00:44:42,477 --> 00:44:44,810
>o endereço do primeiro
caractere e, a partir daí,

871
00:44:44,810 --> 00:44:46,940
>podemos encontrar nosso caminho,
programaticamente, até o fim,

872
00:44:46,940 --> 00:44:48,380
>graças a esse caractere nul.

873
00:44:48,380 --> 00:44:52,220
>Mas acontece que há outra coisa que
podemos fazer com esses endereços
874
00:44:52,220 --> 00:44:53,840
>ou com ponteiros de forma mais geral.

875
00:44:53,840 --> 00:44:55,550
>E isso é conhecido como operação matemática de ponteiro.

876
00:44:55,550 --> 00:44:58,577
>Então, qualquer coisa que seja um número,
claro, podemos fazer matemática.

877
00:44:58,577 --> 00:45:00,410
>E a matemática não
vai ser complicada,

878
00:45:00,410 --> 00:45:03,390
>mas vai ser poderoso
para nós aqui.

879
00:45:03,390 --> 00:45:07,040
>Portanto, vou voltar ao meu
mais recente estado de address.c.

880
00:45:07,040 --> 00:45:11,480
>E deixe-me ir em frente, agora,
e reiterar que podemos imprimir

881
00:45:11,480 --> 00:45:15,800
>os caracteres individuais em uma string,
assim como fizemos na segunda semana,

882
00:45:15,800 --> 00:45:18,270
>usando nossa notação de colchetes.

883
00:45:18,270 --> 00:45:21,170
>Portanto, estou me livrando de todas as
evidências desses endereços por enquanto.

884
00:45:21,170 --> 00:45:23,420
>Estou recompilando este
programa como make address.

885
00:45:23,420 --> 00:45:25,650
>E então vou executar o
./address agora.

886
00:45:25,650 --> 00:45:29,690
>E vejo HI!,
um caractere por linha.

887
00:45:29,690 --> 00:45:34,290
>Mas agora, considere que não precisa
haver um tipo de dados de string.

888
00:45:34,290 --> 00:45:36,320
>Na verdade, podemos tirar
essa roda de treinamento.

889
00:45:36,320 --> 00:45:38,690
>E embora possa parecer um pouco
desconfortável no início,

890
00:45:38,690 --> 00:45:42,620
>se eu excluir esta primeira linha completamente,
como eu acidentalmente omiti de qualquer maneira

891
00:45:42,620 --> 00:45:45,660
>às vezes, não preciso ficar
chamando as coisas de strings.

892
00:45:45,660 --> 00:45:47,570
>Posso descrever como strings verbalmente.

893
00:45:47,570 --> 00:45:49,790
>Posso pensar nelas como
strings, porque strings

894
00:45:49,790 --> 00:45:53,150
>são uma coisa em muitas linguagens
de programação diferentes.

895
00:45:53,150 --> 00:45:56,070
>Mas, por padrão, em C,
simplesmente não existe como um tipo.

896
00:45:56,070 --> 00:45:59,750
>Em vez disso, o tipo tem um nome
um tanto enigmático, char*.

897
00:45:59,750 --> 00:46:02,840
>Mas, novamente, tudo o que isso significa
é que o asterisco está

898
00:46:02,840 --> 00:46:04,010
>marcando o endereço de algo.

899
00:46:04,010 --> 00:46:06,140
>Char significa que é o endereço de um char.

900
00:46:06,140 --> 00:46:09,950
>Então char* dá a você
uma variável de ponteiro

901
00:46:09,950 --> 00:46:12,720
>isso vai apontar para um caractere.

902
00:46:12,720 --> 00:46:16,080
>Então agora, se s é isso,
posso tratar da mesma forma.

903
00:46:16,080 --> 00:46:20,960
>Não há motivo para eu não poder continuar usando
s como uma string estava na segunda semana,

904
00:46:20,960 --> 00:46:22,400
>usando nossa notação de colchetes.

905
00:46:22,400 --> 00:46:24,770
>E posso continuar imprimindo
o HI!

906
00:46:24,770 --> 00:46:27,320
>usando a mesma sintaxe de colchetes.

907
00:46:27,320 --> 00:46:30,170
>Mas há uma outra maneira de fazer isso.

908
00:46:30,170 --> 00:46:35,150
>Se agora eu sei que s
é um endereço,

909
00:46:35,150 --> 00:46:37,760
>Posso me livrar dessa
notação de colchetes.

910
00:46:37,760 --> 00:46:42,860
>E eu posso apenas fazer s*,
porque lembre-se daquele asterisco, além disso

911
00:46:42,860 --> 00:46:47,270
>para ser o novo símbolo que usamos
ao declarar um ponteiro aqui,

912
00:46:47,270 --> 00:46:50,990
>também é o mesmo símbolo,
confuso, admito,

913
00:46:50,990 --> 00:46:53,310
>que costumávamos usar para ir a um endereço.

914
00:46:53,310 --> 00:46:57,650
>Então, se s está armazenando um endereço,
que é por definição um ponteiro,

915
00:46:57,650 --> 00:46:59,900
>s* significa ir para aquele endereço.

916
00:46:59,900 --> 00:47:02,000
>E de acordo com minha
foto anterior, parece

917
00:47:02,000 --> 00:47:08,060
>para ser o caso em que s provavelmente
está em um endereço que começa em 0x123.

918
00:47:08,060 --> 00:47:10,250
>Não será o mesmo em
meu IDE real aqui.

919
00:47:10,250 --> 00:47:12,167
>Será tudo o que o
computador ordenar.

920
00:47:12,167 --> 00:47:14,610
>Mas vai ser exatamente
a mesma ideia.

921
00:47:14,610 --> 00:47:17,150
>Então, agora eu vou ir para as s*.

922
00:47:17,150 --> 00:47:20,130
>E só por diversão, vou
deixar apenas uma linha.

923
00:47:20,130 --> 00:47:23,870
>Então, vou executar
novamente como make address.

924
00:47:23,870 --> 00:47:25,470
>Tudo bem, e agora ./address.

925
00:47:25,470 --> 00:47:30,710
>Devo ver, com sorte,
H e apenas um H. Mas observe isso.

926
00:47:30,710 --> 00:47:34,400
>Se eu sei que s, uma string, é
tecnicamente apenas um endereço,

927
00:47:34,400 --> 00:47:35,960
>na verdade, agora posso fazer cálculos.

928
00:47:35,960 --> 00:47:39,470
>E posso imprimir outro
caractere, seguido por uma nova linha.

929
00:47:39,470 --> 00:47:44,090
>E eu posso ir para, não s,
mas que tal s mais 1.

930
00:47:44,090 --> 00:47:47,600
>Posso fazer uma operação matemática muito simples,
se assim preferir, nesse ponteiro.

931
00:47:47,600 --> 00:47:49,920
>Agora eu vou
recompilar isso.

932
00:47:49,920 --> 00:47:54,800
>Então make address, compila
OK, ./address.

933
00:47:54,800 --> 00:47:56,570
>E eu deveria ver o HI.

934
00:47:56,570 --> 00:48:01,790
>E se eu fizer mais uma linha de código como
esta, printf, % c, \ n,

935
00:48:01,790 --> 00:48:07,130
>s* + 2, agora
posso ir para o caractere
936
00:48:07,130 --> 00:48:10,770
>que está a dois bytes de
distância de qualquer s,

937
00:48:10,770 --> 00:48:12,480
>que, novamente, é o início da string.

938
00:48:12,480 --> 00:48:15,890
>Então, agora, reimprimi HI com o
ponto de exclamação,

939
00:48:15,890 --> 00:48:19,280
>caractere por caractere, mas não
usando este colchete sofisticado

940
00:48:19,280 --> 00:48:24,710
>apenas no sentido de que
era uma espécie de abstração para nós,

941
00:48:24,710 --> 00:48:25,670
>se preferir assim.

942
00:48:25,670 --> 00:48:28,885
>Em vez disso, estou manipulando s pelo que
é, que é um endereço.

943
00:48:28,885 --> 00:48:31,010
>E aqui também, e já
usei essa frase antes,

944
00:48:31,010 --> 00:48:33,710
>aquela notação de colchetes que
introduzimos na semana dois,

945
00:48:33,710 --> 00:48:36,410
>é tecnicamente apenas syntatic sugar.

946
00:48:36,410 --> 00:48:39,500
>Não está fazendo nada
fundamentalmente diferente

947
00:48:39,500 --> 00:48:42,770
>a partir desses asteriscos
e desses endereços.

948
00:48:42,770 --> 00:48:45,440
>está apenas fazendo isso, honestamente,
de uma forma muito mais amigável.

949
00:48:45,440 --> 00:48:49,160
>Eu ainda prefiro, pessoalmente, a
notação de colchetes da segunda semana.

950
00:48:49,160 --> 00:48:54,680
>Mas é a mesma coisa que usar *
e fazer as contas você mesmo.

951
00:48:54,680 --> 00:48:57,020
>Então, C está apenas nos
fornecendo esse recurso útil

952
00:48:57,020 --> 00:49:00,200
>de usar colchetes que fazem
todo esse ponteiro

953
00:49:00,200 --> 00:49:02,360
>aritmético para você.

954
00:49:02,360 --> 00:49:04,290
>Mas, novamente, vamos para
esse baixo nível apenas

955
00:49:04,290 --> 00:49:10,310
>para enfatizar o que está
acontecendo por baixo do capô aqui.

956
00:49:10,310 --> 00:49:13,070
>Tudo bem, deixe-me pausar
aqui para qualquer dúvida.

957
00:49:13,070 --> 00:49:17,290
>E Brian, por favor, sinta-se livre
para verbalizar qualquer coisa de sua parte.

958
00:49:17,290 --> 00:49:19,790
>Brian: Eu vejo uma pergunta que
surgiu sobre o que aconteceria

959
00:49:19,790 --> 00:49:22,233
>se você tentasse imprimir s* + 3.

960
00:49:22,233 --> 00:49:25,400
>David Malan: Então, tenho certeza que
isso vai imprimir o caractere nul.

961
00:49:25,400 --> 00:49:27,233
>Mas vamos em frente e
confirmar aqui,

962
00:49:27,233 --> 00:49:31,760
>%c \n s* + 3.

963
00:49:31,760 --> 00:49:35,120
>Tudo bem, estou me aventurando um pouco

964
00:49:35,120 --> 00:49:38,060
>ao olhar para as coisas que talvez não
deveria estar olhando, porque isso é

965
00:49:38,060 --> 00:49:39,545
>um detalhe de implementação de baixo nível.

966
00:49:39,545 --> 00:49:40,670
>Mas vamos ver o que acontece.

967
00:49:40,670 --> 00:49:43,130
>Ele compila ok, ./address.

968
00:49:43,130 --> 00:49:44,780
>E parece estar em branco.

969
00:49:44,780 --> 00:49:46,730
>Agora, talvez esse seja o caractere Nul.

970
00:49:46,730 --> 00:49:48,980
>Honestamente, não é para ser
um caractere imprimível.

971
00:49:48,980 --> 00:49:52,770
>É este valor sentinela especial
que indica o fim da string.

972
00:49:52,770 --> 00:49:54,020
>Mas eu poderia fazer isso.

973
00:49:54,020 --> 00:49:57,170
>Eu sei desde a segunda semana
que os chars são inteiros,
974
00:49:57,170 --> 00:49:59,670
>e inteiros são chars se eu
quiser pensar neles dessa forma.

975
00:49:59,670 --> 00:50:01,880
>Então, deixe-me mudar
apenas o último caractere

976
00:50:01,880 --> 00:50:03,950
>para usar o formato de código %i.

977
00:50:03,950 --> 00:50:05,690
>Vamos recompilar meu código.

978
00:50:05,690 --> 00:50:07,940
>Eu vou executar o endereço.

979
00:50:07,940 --> 00:50:11,540
>E pronto, HI exclamação 0.

980
00:50:11,540 --> 00:50:16,400
>E há todos os bits 0 representados aqui
como um único dígito decimal, graças a

981
00:50:16,400 --> 00:50:17,570
> % i.

982
00:50:17,570 --> 00:50:19,970
>Agora, posso ficar louco aqui.

983
00:50:19,970 --> 00:50:23,420
>E por que não vamos em frente e
imprimimos não apenas quais caracteres

984
00:50:23,420 --> 00:50:28,580
>estão logo após esta sequência, HI!,
caractere nul,

985
00:50:28,580 --> 00:50:33,770
>por que não vamos - que tal
endereçarmos a 1.000 bytes de distância,

986
00:50:33,770 --> 00:50:35,990
>e com estilo vamos para
dentro do meu computador?
987
00:50:35,990 --> 00:50:38,450
>Vamos recompilar esse ./address.

988
00:50:38,450 --> 00:50:40,460
>OK, nada acontecendo aqui.

989
00:50:40,460 --> 00:50:42,620
>Que tal cerca de 10.000 bytes de distância?

990
00:50:42,620 --> 00:50:44,270
>Eu vou make address.

991
00:50:44,270 --> 00:50:47,990
>Vamos prosseguir e executar essa
falha de segmentação. Tudo bem

992
00:50:47,990 --> 00:50:49,010
>isso não está bom.

993
00:50:49,010 --> 00:50:53,030
>E você pode estar entre os poucos
afortunados que viram esse erro antes

994
00:50:53,030 --> 00:50:54,440
>ao tocar a memória que não deveria.

995
00:50:54,440 --> 00:50:56,607
>E vamos considerar isso
deliberadamente hoje.

996
00:50:56,607 --> 00:50:59,540
>Mas uma falha de segmentação,
significa que você fez algo

997
00:50:59,540 --> 00:51:01,430
>errado em algum lugar do seu código.

998
00:51:01,430 --> 00:51:04,000
>E isso tende a significar que
você tocou um segmento de memória

999
00:51:04,000 --> 00:51:05,000
>que você não deveria ter tocado.

1000
00:51:05,000 --> 00:51:08,750
>Eu não me interesso, honestamente,
em olhar 10.000 bytes de distância

1001
00:51:08,750 --> 00:51:11,420
>da memória que sei
que pertence à string.

1002
00:51:11,420 --> 00:51:14,670
>Isso é como olhar arbitrariamente em
qualquer lugar na memória do seu computador,

1003
00:51:14,670 --> 00:51:16,890
>que provavelmente, ao que parece,
não é uma boa ideia.

1004
00:51:16,890 --> 00:51:19,000
>Mais sobre esse assunto daqui a pouco.

1005
00:51:19,000 --> 00:51:21,470
>Então, vamos considerar, agora,
algumas das implicações

1006
00:51:21,470 --> 00:51:25,130
>desses detalhes de
implementação subjacentes

1007
00:51:25,130 --> 00:51:28,580
>e considere, agora, a partir da semana passada,
porque fizemos algumas coisas do jeito

1008
00:51:28,580 --> 00:51:30,590
>que fizemos nas últimas semanas, na verdade.

1009
00:51:30,590 --> 00:51:32,360
>Então string é um char*.

1010
00:51:32,360 --> 00:51:33,860
>E vamos, agora, considerar um exemplo.

1011
00:51:33,860 --> 00:51:37,260
>Vamos diminuir o zoom na minha memória,
apenas para que eu possa incluir mais de uma vez.

1012
00:51:37,260 --> 00:51:39,620
>Vamos considerar um exemplo
onde eu poderia querer escrever
1013
00:51:39,620 --> 00:51:42,570
>um programa que compara duas strings.

1014
00:51:42,570 --> 00:51:45,830
>Vamos prosseguir e escrever um novo
código aqui em um novo arquivo desta vez,

1015
00:51:45,830 --> 00:51:48,350
>chamado, por exemplo, compare.c.

1016
00:51:48,350 --> 00:51:50,480
>Meu objetivo com este
programa, simplesmente, é

1017
00:51:50,480 --> 00:51:55,580
>ser imprimir o conteúdo
de - ou melhor, comparar

1018
00:51:55,580 --> 00:51:57,590
>duas strings que o usuário pode inserir.

1019
00:51:57,590 --> 00:52:00,040
>Vou prosseguir e
incluir cs59.h,

1020
00:52:00,040 --> 00:52:02,810
>não porque eu continue querendo a
string, digamos,

1021
00:52:02,810 --> 00:52:05,750
>mas porque eu quero usar get string
apenas por conveniência.

1022
00:52:05,750 --> 00:52:08,180
>Mas também tiraremos essa roda
de treinamento daqui a pouco.

1023
00:52:08,180 --> 00:52:10,520
>E neste programa, vou
em frente e primeiro

1024
00:52:10,520 --> 00:52:11,690
>vou usar isso,
e não get string ainda.

1025
00:52:11,690 --> 00:52:14,450
>Vamos prosseguir e manter as
coisas simples e começar com get int.

1026
00:52:14,450 --> 00:52:16,910
>E vou pedir ao usuário uma variável i.

1027
00:52:16,910 --> 00:52:19,340
>E deixe-me fazer outro desses
get int e perguntar

1028
00:52:19,340 --> 00:52:21,270
>ao usuário por um valor para j.

1029
00:52:21,270 --> 00:52:24,665
>E então agora eu vou
simplesmente dizer, se i é igual a j,

1030
00:52:24,665 --> 00:52:28,790
>então vá em frente e imprima o mesmo.

1031
00:52:28,790 --> 00:52:31,770
>Eu vou imprimir de forma diferente.

1032
00:52:31,770 --> 00:52:35,930
>Então, esta é a primeira semana, onde
estou usando algumas variáveis.

1033
00:52:35,930 --> 00:52:38,300
>Estou usando uma condição com
duas ramificações e estou

1034
00:52:38,300 --> 00:52:42,990
>usando printf para imprimir se essas
duas variáveis, i e j, são as mesmas.

1035
00:52:42,990 --> 00:52:44,930
>Então, vamos compilar isso.

1036
00:52:44,930 --> 00:52:45,950
>Tudo está bem.

1037
00:52:45,950 --> 00:52:49,310
>Execute compare e deixe-me
dar os dígitos 1 e 2.

1038
00:52:49,310 --> 00:52:50,630
>E, são diferentes.

1039
00:52:50,630 --> 00:52:53,400
>Agora eu vou dar
1 e 1, e são iguais.

1040
00:52:53,400 --> 00:52:56,270
>Então eu acho, logicamente, prova
por exemplo, se preferir,

1041
00:52:56,270 --> 00:52:57,860
>este programa parece correto.

1042
00:52:57,860 --> 00:53:02,630
>Mas deixe-me torná-lo aparentemente
incorreto, não usando números inteiros.

1043
00:53:02,630 --> 00:53:05,840
>Mas que tal usar strings em vez disso.

1044
00:53:05,840 --> 00:53:07,988
>vou continuar
e criar uma string.

1045
00:53:07,988 --> 00:53:10,280
>Embora, não, eu não precise mais
daquela roda de treinamento.

1046
00:53:10,280 --> 00:53:15,300
>Vamos fazer char* s igual a get string de s.

1047
00:53:15,300 --> 00:53:17,300
>Mas, novamente, embora
eu esteja chamando de char*,

1048
00:53:17,300 --> 00:53:19,580
>ainda é uma string como
se fosse semanas atrás.

1049
00:53:19,580 --> 00:53:23,510
>Vou criar outra string chamada t,
apenas para manter o nome curto.

1050
00:53:23,510 --> 00:53:25,100
>E vai obter -

1051
00:53:25,100 --> 00:53:26,730
>t obterá esse valor.

1052
00:53:26,730 --> 00:53:30,140
>E deixe-me apenas, muito
ingenuamente, mas razoavelmente,

1053
00:53:30,140 --> 00:53:34,310
>dizer que se s é igual a t, vamos
prosseguir e imprimir o mesmo.

1054
00:53:34,310 --> 00:53:38,000
>E caso contrário, vamos
prosseguir e imprimir diferente.

1055
00:53:38,000 --> 00:53:41,240
>Portanto, o mesmo código exato, apenas
diferentes tipos de dados, e usando

1056
00:53:41,240 --> 00:53:42,830
>get string em vez de get int.

1057
00:53:42,830 --> 00:53:47,360
>Eu vou fazer make compare,
parece compilar OK, ./compare.

1058
00:53:47,360 --> 00:53:51,770
>Vamos prosseguir e digitar HI! -

1059
00:53:51,770 --> 00:53:53,570
>woops, HI !.

1060
00:53:53,570 --> 00:53:55,220
>Vamos prosseguir e digitar HI! novamente.

1061
00:53:55,220 --> 00:53:57,500
>E voila, diferente.

1062
00:53:57,500 --> 00:54:01,010
>E esqueci minha \, mas esse
parece ser o menor dos meus problemas.

1063
00:54:01,010 --> 00:54:05,240
>Vamos recompilar isso, make compare,
e agora, deixe-me executá-lo novamente.

1064
00:54:05,240 --> 00:54:07,130
>Que tal fazer um teste rápido.

1065
00:54:07,130 --> 00:54:09,010
>David, Brian, esses são
definitivamente diferentes.

1066
00:54:09,010 --> 00:54:09,580
>Tudo bem.

1067
00:54:09,580 --> 00:54:11,240
>Portanto, o programa parece funcionar.

1068
00:54:11,240 --> 00:54:13,150
>Que tal David, David?

1069
00:54:13,150 --> 00:54:14,140
>Também diferente.

1070
00:54:14,140 --> 00:54:15,370
>Huh, deixe-me tentar novamente.

1071
00:54:15,370 --> 00:54:18,600
>Brian, Brian, também diferentes.

1072
00:54:18,600 --> 00:54:21,570
>Mas tenho certeza de que
essas strings são as mesmas.

1073
00:54:21,570 --> 00:54:24,180
>Por que este programa pode ter falhas?

1074
00:54:24,180 --> 00:54:28,582
>O que há de errado com
este programa agora?

1075
00:54:28,582 --> 00:54:30,290
>BRIAN: Algumas pessoas
no chat estão

1076
00:54:30,290 --> 00:54:32,750
>dizendo que não estamos
comparando os caracteres,

1077
00:54:32,750 --> 00:54:34,370
>estamos comparando os endereços.
1078
00:54:34,370 --> 00:54:37,377
>DAVID MALAN: Sim, essa é a
conclusão lógica de hoje

1079
00:54:37,377 --> 00:54:38,960
>na definição do que uma string é.

1080
00:54:38,960 --> 00:54:41,750
>Se uma string é o endereço
de seu primeiro caractere,

1081
00:54:41,750 --> 00:54:44,450
>então, se você estiver
literalmente fazendo s igual a t,

1082
00:54:44,450 --> 00:54:46,697
>você está comparando esses dois endereços.

1083
00:54:46,697 --> 00:54:48,530
>E provavelmente
serão diferentes,

1084
00:54:48,530 --> 00:54:50,990
>mesmo se eu digitar a mesma
coisa, porque toda vez que

1085
00:54:50,990 --> 00:54:55,010
>chamei get int ou get string, meio que
inseriu na entrada do usuário

1086
00:54:55,010 --> 00:54:56,750
>em algum lugar da memória do meu computador.

1087
00:54:56,750 --> 00:55:00,560
>Mas agora temos as ferramentas, honestamente,
para responder ou examinar esta resposta

1088
00:55:00,560 --> 00:55:01,130
>nós mesmos.

1089
00:55:01,130 --> 00:55:03,230
>Vamos simplificar
este programa.

1090
00:55:03,230 --> 00:55:06,050
>E vamos, apenas para uma rápida
verificação, imprimir s.

1091
00:55:06,050 --> 00:55:10,610
>E vamos prosseguir e imprimir
usando uma nova linha após cada,

1092
00:55:10,610 --> 00:55:12,350
>só para vermos quais são as strings.

1093
00:55:12,350 --> 00:55:16,830
>Então, agora eu vou fazer isso de novo,
make compare, compila OK, ./

1094
00:55:16,830 --> 00:55:17,330
>compare.

1095
00:55:17,330 --> 00:55:19,310
>Vamos digitar HI, HI.

1096
00:55:19,310 --> 00:55:21,710
>E eles parecem ser visualmente iguais.

1097
00:55:21,710 --> 00:55:24,770
>Mas lembre-se que, agora, eu tenho
esse outro código de formato,

1098
00:55:24,770 --> 00:55:27,080
>de modo que agora posso
começar a tratar strings

1099
00:55:27,080 --> 00:55:29,330
>como os endereços que são tecnicamente.

1100
00:55:29,330 --> 00:55:33,140
>Então, deixe-me mudar a % s
para a % p em ambos os lugares.

1101
00:55:33,140 --> 00:55:37,610
>Vamos então recompilar o programa, e agora,
execute-o novamente e compare com HI e HI

1102
00:55:37,610 --> 00:55:38,690
>digitados de forma idêntica.

1103
00:55:38,690 --> 00:55:43,100
>Mas observe, eles acabaram em locais
de memória ligeiramente diferentes.

1104
00:55:43,100 --> 00:55:46,820
>Mesmo que eu tenha coincidentemente
digitado a mesma coisa, C e meu computador

1105
00:55:46,820 --> 00:55:52,097
>não serão tão presunçosos a ponto de usar
os mesmos bytes para ambas as strings.

1106
00:55:52,097 --> 00:55:53,930
>Isso não vai me dar
muita flexibilidade

1107
00:55:53,930 --> 00:55:55,490
>se eu quiser mudar um ou outro.

1108
00:55:55,490 --> 00:55:58,490
>Isso vai colocar, de forma muito
simplista, incluir um pedaço neste pedaço de memória

1109
00:55:58,490 --> 00:56:00,240
>e o outro neste pedaço de memória.

1110
00:56:00,240 --> 00:56:03,680
>E, esses endereços são
respectivamente, mas arbitrariamente,

1111
00:56:03,680 --> 00:56:07,220
>0x22fe670 e 0x22fe6b0.

1112
00:56:09,770 --> 00:56:12,500
>Portanto, estão separados a alguma distância.

1113
00:56:12,500 --> 00:56:15,810
>Mas, novamente, cabe ao computador
decidir onde colocá-los.

1114
00:56:15,810 --> 00:56:18,310
>Então, o que está acontecendo
dentro da memória do computador?

1115
00:56:18,310 --> 00:56:22,010
>Bem, vamos considerar se, por exemplo,
este é s, meu ponteiro, ou ,
1116
00:56:22,010 --> 00:56:22,640
>minha string.

1117
00:56:22,640 --> 00:56:23,810
>Mas agora é um ponteiro.

1118
00:56:23,810 --> 00:56:25,060
>É o endereço de algo.

1119
00:56:25,060 --> 00:56:28,250
>Observe que eu o desenhei
como ocupando oito quadrados,

1120
00:56:28,250 --> 00:56:31,680
>porque, novamente, um ponteiro em
sistemas modernos tem oito bytes.

1121
00:56:31,680 --> 00:56:33,320
>É por isso que essa coisa é tão grande.

1122
00:56:33,320 --> 00:56:37,100
>Enquanto isso, quando eu digito algo
como HI!,

1123
00:56:37,100 --> 00:56:38,720
>então acaba em algum lugar na memória.

1124
00:56:38,720 --> 00:56:40,440
>Nós não sabemos ou não
nos importamos onde está.

1125
00:56:40,440 --> 00:56:42,773
>Então, vamos simplesmente dizer
que acaba ficando ali

1126
00:56:42,773 --> 00:56:43,850
>na memória do meu computador.

1127
00:56:43,850 --> 00:56:46,730
>Agora, cada um desses bytes,
claro, tem um endereço.

1128
00:56:46,730 --> 00:56:48,950
>Eu não necessariamente sei ou
me importo com o que são.
1129
00:56:48,950 --> 00:56:52,040
>Mas para fins de explicação, vamos
numerá-los novamente como antes,

1130
00:56:52,040 --> 00:56:56,810
>0x123, 0x124, 0x125, 0x126.

1131
00:56:56,810 --> 00:57:02,960
>Quando eu atribuo s à esquerda o
valor de get string à direita,

1132
00:57:02,960 --> 00:57:04,670
>get string, o que vai fazer?

1133
00:57:04,670 --> 00:57:07,640
>Bem, todo esse tempo desde a primeira
semana, desde que você o tem usado,

1134
00:57:07,640 --> 00:57:11,970
>obtém uma string e devolve
a você como um valor de retorno.

1135
00:57:11,970 --> 00:57:13,680
>Mas o que isso significa?

1136
00:57:13,680 --> 00:57:18,200
>Bem, se uma string é um endereço,
o valor de retorno de uma função

1137
00:57:18,200 --> 00:57:23,030
>como get string é para retornar,
não a string em si, porque isso é

1138
00:57:23,030 --> 00:57:24,740
>um tipo de conceito de alto nível.

1139
00:57:24,740 --> 00:57:27,050
>O que get string
sempre fez por nós

1140
00:57:27,050 --> 00:57:29,810
>é retornar o endereço
da string, ou mais

1141
00:57:29,810 --> 00:57:33,410
>especificamente, o endereço do
primeiro caractere na string.

1142
00:57:33,410 --> 00:57:39,740
>E então o que é tecnicamente armazenado em s,
para ser claro, é esse endereço, 0x123.

1143
00:57:39,740 --> 00:57:43,400
>Não está retornando a string inteira,
o H, o I, o ponto de exclamação.

1144
00:57:43,400 --> 00:57:46,040
>Em vez disso, está retornando
apenas um valor para você.

1145
00:57:46,040 --> 00:57:50,990
>está retornando apenas para você o
endereço do primeiro caractere daquela string.

1146
00:57:50,990 --> 00:57:54,500
>Mas, novamente, tudo isso é
muito bom para apenas s.

1147
00:57:54,500 --> 00:57:55,880
>O que está acontecendo com t?

1148
00:57:55,880 --> 00:57:58,910
>t é mais ou menos a mesma história, porque
estou chamando get string novamente.

1149
00:57:58,910 --> 00:58:02,390
>t vai ser atribuído ao endereço
do primeiro caractere

1150
00:58:02,390 --> 00:58:03,500
>desta versão do HI.

1151
00:58:03,500 --> 00:58:13,160
>E vamos apenas dizer que está
em 0x456, 0x457, 0x458 e 0x459.

1152
00:58:13,160 --> 00:58:16,873
>E neste ponto, t vai
assumir o valor de 0x456.

1153
00:58:16,873 --> 00:58:19,790
>E agora, neste ponto, honestamente,
estamos entrando nas minúcias.
1154
00:58:19,790 --> 00:58:21,665
>Vamos começar
a abstrair tudo isso

1155
00:58:21,665 --> 00:58:23,870
>e usar setas para apontar para os valores.

1156
00:58:23,870 --> 00:58:26,720
>E, essas setas
representam apenas ponteiros

1157
00:58:26,720 --> 00:58:29,190
>quando paramos de nos preocupar
com os endereços específicos.

1158
00:58:29,190 --> 00:58:32,300
>Então s é um
ponteiro, uma variável que aponta

1159
00:58:32,300 --> 00:58:34,070
>no primeiro caractere de HI aqui.

1160
00:58:34,070 --> 00:58:38,490
>t é uma variável apontando
para o primeiro caractere de HI ali.

1161
00:58:38,490 --> 00:58:41,540
>E então, quando você está
comparando duas strings

1162
00:58:41,540 --> 00:58:45,440
>como eu estava antes na versão
anterior do meu programa,

1163
00:58:45,440 --> 00:58:53,540
>onde eu estava verificando se s é igual a t,
eu estava, comparando s e t.

1164
00:58:53,540 --> 00:58:55,130
>O que são s e t?

1165
00:58:55,130 --> 00:59:01,640
>s e t, respectivamente,
são 0x123 e 0x456,

1166
00:59:01,640 --> 00:59:03,770
>ou quaisquer que sejam
os valores reais,

1167
00:59:03,770 --> 00:59:06,320
>que não vão ser os
mesmos porque acabam por

1168
00:59:06,320 --> 00:59:09,920
>apontar para diferentes blocos de memória.

1169
00:59:09,920 --> 00:59:12,110
>Tudo bem, quem se importa?

1170
00:59:12,110 --> 00:59:14,630
>Isso tudo é um bom
exercício intelectual.

1171
00:59:14,630 --> 00:59:15,512
>Mas quem se importa?

1172
00:59:15,512 --> 00:59:16,970
>Bem, como podemos resolver este problema?

1173
00:59:16,970 --> 00:59:20,480
>Vamos considerar o que eu
fiz em uma demonstração anterior.

1174
00:59:20,480 --> 00:59:23,955
>Eu meio que mencionei preventivamente que
existe esta função, comparação de strings,

1175
00:59:23,955 --> 00:59:25,580
>que permite que você compare duas strings.

1176
00:59:25,580 --> 00:59:28,040
>E eu prometi que
explicaríamos

1177
00:59:28,040 --> 00:59:31,573
>porque usamos str compare ao invés de
apenas usar o sinal de igual igual.

1178
00:59:31,573 --> 00:59:33,740
>Bem, para usar esta função,
vou precisar adicionar
1179
00:59:33,740 --> 00:59:37,910
>string.h até aqui pela última vez.

1180
00:59:37,910 --> 00:59:40,790
>Mas se string compare s t,
vou recompilar isso,

1181
00:59:40,790 --> 00:59:43,160
>compare ./compare

1182
00:59:43,160 --> 00:59:45,710
>Agora, deixe-me digitar HI!
e HI! identicamente.

1183
00:59:45,710 --> 00:59:47,870
>Agora, eles ainda parecem ser diferentes.

1184
00:59:47,870 --> 00:59:51,680
>E caramba, cometi o mesmo
erro estúpido da última vez.

1185
00:59:51,680 --> 00:59:57,170
>Alguém sabe que erro cometi
ao comparar duas strings?

1186
00:59:57,170 --> 01:00:00,590
>De alguma forma, pareço ser
muito bom em cometer esse erro.

1187
01:00:00,590 --> 01:00:03,440
>BRIAN: Ibrahim está sugerindo que
você adicione um igual igual a zero.

1188
01:00:03,440 --> 01:00:04,398
>DAVID MALAN: Obrigado.

1189
01:00:04,398 --> 01:00:05,390
>Ibrahim está certo.

1190
01:00:05,390 --> 01:00:08,000
>O valor de retorno,
lembrem, de str compare,

1191
01:00:08,000 --> 01:00:13,040
>é retornar 0 se forem iguais,
um número negativo se um vier
1192
01:00:13,040 --> 01:00:16,430
>antes do outro, e um número positivo
se um vier depois do outro,

1193
01:00:16,430 --> 01:00:18,600
>como na ordem ASCIIbética.

1194
01:00:18,600 --> 01:00:21,440
>Então o que eu deveria ter feito,
da última vez e desta vez,

1195
01:00:21,440 --> 01:00:23,600
>a verificação de igualdade com 0.

1196
01:00:23,600 --> 01:00:26,220
>Eu vou
recompilar este programa.

1197
01:00:26,220 --> 01:00:27,050
>Tudo bem.

1198
01:00:27,050 --> 01:00:29,090
>Agora, deixe-me executar novamente este programa com o HI!

1199
01:00:29,090 --> 01:00:30,230
>duas vezes.

1200
01:00:30,230 --> 01:00:31,940
>Voila, são iguais.

1201
01:00:31,940 --> 01:00:34,580
>E só para ter certeza,
deixe-me fazer outra verificação.

1202
01:00:34,580 --> 01:00:38,810
>Vou fazer David e Brian, o
que deve ser, diferente.

1203
01:00:38,810 --> 01:00:42,050
>Então agora, novamente, eu
não fiz nada diferente da última vez.

1204
01:00:42,050 --> 01:00:47,420
>Mas agora estou pensando nessas strings
como sendo fundamentalmente apenas
1205
01:00:47,420 --> 01:00:48,173
>seus endereços.

1206
01:00:48,173 --> 01:00:50,090
>E então, agora, vamos tornar
isso pertinente.

1207
01:00:50,090 --> 01:00:52,160
>Vamos prosseguir e
criar um novo arquivo.

1208
01:00:52,160 --> 01:00:56,590
>E vamos, razoavelmente, tentar copiar
uma string e fazer alterações nela.

1209
01:00:56,590 --> 01:00:57,840
>Então, vou prosseguir aqui.

1210
01:00:57,840 --> 01:01:00,230
>E apenas por conveniência, ainda
vou usar a biblioteca CS50,

1211
01:01:00,230 --> 01:01:02,300
>não para o tipo de dados
string, mas apenas para o

1212
01:01:02,300 --> 01:01:06,200
>get string function, que veremos é
mais útil do que outras coisas -

1213
01:01:06,200 --> 01:01:07,790
>do que outras maneiras de fazer as coisas.

1214
01:01:07,790 --> 01:01:11,630
>E vou prosseguir e incluir
include standard io ponto h.

1215
01:01:11,630 --> 01:01:17,450
>E vou prosseguir e incluir,
que tal, string.h.

1216
01:01:17,450 --> 01:01:20,000
>Eu vou fazer
int main void.

1217
01:01:20,000 --> 01:01:22,790
>E deixe-me ir em frente, neste programa,
e criar uma string.

1218
01:01:22,790 --> 01:01:24,540
>Mas observe, não vamos
chamar mais de string.

1219
01:01:24,540 --> 01:01:26,030
>Vamos chamar de char*.

1220
01:01:26,030 --> 01:01:28,380
>Então, novamente, comece a
tirar a roda de treinamento.

1221
01:01:28,380 --> 01:01:31,312
>E vou prosseguir e obter
uma string chamada s.

1222
01:01:31,312 --> 01:01:33,020
>E então vou pegar
outra string.

1223
01:01:33,020 --> 01:01:34,062
>Mas não vou chamar assim.

1224
01:01:34,062 --> 01:01:36,230
>Vou chamar de char* t.

1225
01:01:36,230 --> 01:01:37,400
>E eu quero copiar s.

1226
01:01:37,400 --> 01:01:40,790
>E então você pode pensar, com base na semana
um, semana dois, e desde então, que OK,

1227
01:01:40,790 --> 01:01:42,890
>se você quiser copiar uma
variável, basta fazê-lo.

1228
01:01:42,890 --> 01:01:44,690
>Quer dizer, usamos o
operador de atribuição

1229
01:01:44,690 --> 01:01:48,530
>para copiar uma variável da direita para
a esquerda para inteiros, para chars,
1230
01:01:48,530 --> 01:01:50,600
>e para outros tipos de dados, talvez também.

1231
01:01:50,600 --> 01:01:54,690
>Vou prosseguir, agora, e fazer uma
alteração na string original.

1232
01:01:54,690 --> 01:01:56,270
>Então, agora eu vou fazer isso.

1233
01:01:56,270 --> 01:02:01,280
>Vamos continuar e dizer, vamos
mudar o primeiro caractere de t

1234
01:02:01,280 --> 01:02:02,780
>em maiúsculas.

1235
01:02:02,780 --> 01:02:04,940
>Lembre-se de que existe
esta função, to upper,

1236
01:02:04,940 --> 01:02:09,170
>que leva, como entrada, um caractere,
como o primeiro caractere em t,

1237
01:02:09,170 --> 01:02:11,120
>e retorna a versão em maiúsculas.

1238
01:02:11,120 --> 01:02:14,240
>Agora, para usar o to upper, preciso
de outro arquivo de cabeçalho,

1239
01:02:14,240 --> 01:02:17,990
>que pelo que me lembro, de algumas
semanas atrás, é o ctype.h.

1240
01:02:17,990 --> 01:02:20,750
>Então, volto
e coloco isso lá.

1241
01:02:20,750 --> 01:02:23,280
>E agora, deixe-me ir em frente
e imprimir essas duas strings.

1242
01:02:23,280 --> 01:02:27,500
>Eu vou imprimir
s como sendo % s.

1243
01:02:27,500 --> 01:02:33,990
>Agora eu vou imprimir o
valor de t com % s como segue.

1244
01:02:33,990 --> 01:02:36,680
>Então, novamente, o que estou fazendo
é recebendo uma string do usuário.

1245
01:02:36,680 --> 01:02:40,490
>E a única coisa nova aqui é char
asterisco hoje, que é sinônimo de string.

1246
01:02:40,490 --> 01:02:44,270
>Na linha 10 aqui, estou copiando a
string da direita para a esquerda.

1247
01:02:44,270 --> 01:02:47,330
>E então estou colocando em
maiúscula apenas a primeira letra

1248
01:02:47,330 --> 01:02:49,640
>na cópia, também conhecida como t.

1249
01:02:49,640 --> 01:02:51,140
>E então estou imprimindo ambas.

1250
01:02:51,140 --> 01:02:54,290
>Então agora eu vou
fazer uma cópia, compila OK.

1251
01:02:54,290 --> 01:02:56,510
>Faça copy-- cópia ponto-barra.

1252
01:02:56,510 --> 01:03:00,020
>Vamos prosseguir e digitar hi!
em minúsculas, todas em minúsculas,

1253
01:03:00,020 --> 01:03:00,920
>e, em seguida, entre.

1254
01:03:00,920 --> 01:03:03,830
>E voila.

1255
01:03:03,830 --> 01:03:10,760
>Parece que de alguma forma eu coloquei
S e T em maiúscula, embora eu apenas

1256
01:03:10,760 --> 01:03:17,080
>chamado to upper em T.
Brian, alguma ideia

1257
01:03:17,080 --> 01:03:24,820
>do grupo sobre por que eu acidentalmente
e erroneamente converti em maiúscula

1258
01:03:24,820 --> 01:03:26,260
>ambas, de alguma forma?

1259
01:03:26,260 --> 01:03:29,735
>BRIAN: Algumas pessoas estão dizendo
que t é um pseudônimo de s.

1260
01:03:29,735 --> 01:03:32,860
>DAVID MALAN: Apenas um pseudônimo de s, essa
é uma maneira razoável de pensar nisso,

1261
01:03:32,860 --> 01:03:33,360
>certo.

1262
01:03:33,360 --> 01:03:38,320
>E, mais precisamente, algum outro pensamento sobre
por que isso está incorreto de alguma forma?

1263
01:03:38,320 --> 01:03:41,540
>BRIAN: Peter agora está sugerindo
que tenham o mesmo endereço.

1264
01:03:41,540 --> 01:03:45,880
>DAVID MALAN: Sim, mais especificamente,
tudo o que fiz foi copiar s para t.

1265
01:03:45,880 --> 01:03:48,040
>Mas, de novo, o que é "s" hoje?

1266
01:03:48,040 --> 01:03:49,390
>É apenas um endereço.

1267
01:03:49,390 --> 01:03:51,040
>Então, sim, copiei o s.
1268
01:03:51,040 --> 01:03:54,820
>Mas eu copiei o que
significa copiar seu endereço, 0x123,

1269
01:03:54,820 --> 01:03:55,820
>ou seja o que for.

1270
01:03:55,820 --> 01:04:01,180
>E então na linha 12, observe que
estou mudando t colocando-o em letras maiúsculas.

1271
01:04:01,180 --> 01:04:04,130
>Mas t está no mesmo endereço de s.

1272
01:04:04,130 --> 01:04:08,130
>Então, estou
mudando um na mesma string.

1273
01:04:08,130 --> 01:04:10,630
>Então, se pensarmos nisso em
termos de memória do computador,

1274
01:04:10,630 --> 01:04:12,088
>vamos considerar o que acabei de fazer.

1275
01:04:12,088 --> 01:04:13,570
>Vamos limpar a memória do computador.

1276
01:04:13,570 --> 01:04:15,290
>Vamos tratar o "s", como fizemos antes.

1277
01:04:15,290 --> 01:04:18,250
>Deixa eu colocar hi! para baixo como antes,
mas todas em minúsculas desta vez.

1278
01:04:18,250 --> 01:04:23,320
>E lembre-se de que podem ser os
endereços 0x123, 124, 125 e 126.

1279
01:04:23,320 --> 01:04:26,350
>E agora, se considerarmos
que tecnicamente

1280
01:04:26,350 --> 01:04:29,740
>contém o endereço do
primeiro caractere, 0x123,
1281
01:04:29,740 --> 01:04:34,960
>e eu continuo criando uma nova variável,
t, e atribuo t o valor de s,

1282
01:04:34,960 --> 01:04:36,970
>eu tenho que interpretar essa afirmação literalmente.

1283
01:04:36,970 --> 01:04:39,670
>Estou literalmente colocando 0x123 aqui.

1284
01:04:39,670 --> 01:04:41,770
>E se agora abstrairmos
esses detalhes apenas

1285
01:04:41,770 --> 01:04:44,020
>para deixar mais claro visualmente
o que está acontecendo,

1286
01:04:44,020 --> 01:04:48,070
>isso é quase como dizer
que ambos os pontos s e t

1287
01:04:48,070 --> 01:04:49,750
>estão no mesmo local na memória.

1288
01:04:49,750 --> 01:04:52,297
>Então, sim, nesse sentido, t
é um apelido para s,

1289
01:04:52,297 --> 01:04:54,130
>que é uma maneira razoável
de pensar nisso.

1290
01:04:54,130 --> 01:04:56,920
>Mas, na verdade, t é idêntico a s.

1291
01:04:56,920 --> 01:04:59,110
>Então, quando você usa
a notação de colchetes

1292
01:04:59,110 --> 01:05:02,290
>para ir para o primeiro caractere
de t, você está, equivalentemente,

1293
01:05:02,290 --> 01:05:04,750
>indo para o primeiro caractere em s.

1294
01:05:04,750 --> 01:05:06,200
>São o mesmo.

1295
01:05:06,200 --> 01:05:10,390
>Então, quando eu chamo to upper, estou
chamando esse caractere, que é claro, é

1296
01:05:10,390 --> 01:05:12,970
>o único h na história.

1297
01:05:12,970 --> 01:05:16,240
>E quando eu print s e
print t, printf é

1298
01:05:16,240 --> 01:05:18,610
>seguindo essas mesmas migalhas
de pão, se preferir,

1299
01:05:18,610 --> 01:05:24,070
>e, finalmente, exibindo o mesmo
valor como tendo sido alterado.

1300
01:05:24,070 --> 01:05:27,220
>Portanto, parece que precisamos
repensar fundamentalmente

1301
01:05:27,220 --> 01:05:28,990
>como estamos copiando strings.

1302
01:05:28,990 --> 01:05:34,300
>E deixe-me perguntar, se esta é a maneira
errada de copiar uma string na outra, qual

1303
01:05:34,300 --> 01:05:35,350
>é o caminho certo?

1304
01:05:35,350 --> 01:05:39,340
>Mesmo que você não tenha as funções
em mente ou o vocabulário certo,

1305
01:05:39,340 --> 01:05:43,750
>apenas intuitivamente, se quisermos copiar
uma string da maneira que um humano faria

1306
01:05:43,750 --> 01:05:50,020
>pense em copiar uma no outra,
como uma fotografia ou fotocópia,

1307
01:05:50,020 --> 01:05:52,610
>como podemos fazer isso?

1308
01:05:52,610 --> 01:05:54,460
>Alguma ideia, Brian?

1309
01:05:54,460 --> 01:05:57,430
>BRIAN: Sim, Sofia sugeriu fazer
um loop de alguma forma

1310
01:05:57,430 --> 01:05:59,948
>com elementos em s e colocá-los em t.

1311
01:05:59,948 --> 01:06:01,240
>DAVID MALAN: Sim, gosto disso.

1312
01:06:01,240 --> 01:06:04,120
>Então, faça um loop sobre os
elementos de s e coloque-os em t.

1313
01:06:04,120 --> 01:06:05,800
>Portanto, parece mais trabalho.

1314
01:06:05,800 --> 01:06:07,660
>Mas isso é, novamente,
o que vamos ter

1315
01:06:07,660 --> 01:06:09,582
>que fazer se quisermos pensar nisso -

1316
01:06:09,582 --> 01:06:12,790
>se quisermos aceitar o fato de que essas
coisas, s e t, são apenas endereços,

1317
01:06:12,790 --> 01:06:15,550
>agora vamos ter que seguir
essas migalhas de pão.

1318
01:06:15,550 --> 01:06:18,790
>Portanto, vamos prosseguir e considerar
uma variante deste programa.

1319
01:06:18,790 --> 01:06:24,520
>Vou continuar aqui e mudar isso para
que eu ainda esteja recebendo uma string s.

1320
01:06:24,520 --> 01:06:28,390
>Mas agora, deixe-me ir em frente
e propor exatamente isso,

1321
01:06:28,390 --> 01:06:30,340
>que copiemos os caracteres individuais.

1322
01:06:30,340 --> 01:06:32,320
>Mas preciso copiá-los em algum lugar.

1323
01:06:32,320 --> 01:06:35,200
>Então, eu sinto como se mais uma
etapa neste processo de copiar uma string

1324
01:06:35,200 --> 01:06:37,750
>precisa me retornar
alguma memória adicional.

1325
01:06:37,750 --> 01:06:40,840
>Se eu tiver Hi!
em caráter nulo,

1326
01:06:40,840 --> 01:06:43,150
>eu preciso, agora, de alguma forma,
assumir o controle desta situação

1327
01:06:43,150 --> 01:06:48,320
>e dizer ao computador, de alguma forma, em
código, me dê mais quatro bytes de memória

1328
01:06:48,320 --> 01:06:53,390
>para que eu tenha um local para t
no qual copiar esses caracteres.

1329
01:06:53,390 --> 01:06:55,360
>Então, aqui está uma nova função hoje.

1330
01:06:55,360 --> 01:06:59,470
>Se eu quiser criar uma string t,
também conhecido hoje como char*,

1331
01:06:59,470 --> 01:07:02,680
>há uma nova função que podemos
usar chamada malloc, que

1332
01:07:02,680 --> 01:07:04,720
>representa a alocação de memória.

1333
01:07:04,720 --> 01:07:08,200
>Esta é uma função muito sofisticada que,
felizmente, é muito simples de usar.

1334
01:07:08,200 --> 01:07:10,390
>Leva, como entrada, apenas um número.

1335
01:07:10,390 --> 01:07:14,480
>Quantos bytes de memória você
deseja solicitar ao computador?

1336
01:07:14,480 --> 01:07:16,000
>Então, como faço isso?

1337
01:07:16,000 --> 01:07:20,110
>Bem, HI! .\0,
eu poderia literalmente dizer apenas quatro.

1338
01:07:20,110 --> 01:07:21,850
>Mas isso não parece muito dinâmico.

1339
01:07:21,850 --> 01:07:26,410
>Acho que posso implementar isso programaticamente
com um pouco mais de elegância.

1340
01:07:26,410 --> 01:07:30,370
>Eu vou dizer,
me dê tantos bytes

1341
01:07:30,370 --> 01:07:35,200
>quanto houver de caracteres em s mais 1.

1342
01:07:35,200 --> 01:07:37,090
>Mais 1, por que estou fazendo isso?

1343
01:07:37,090 --> 01:07:40,773
>Bem, HI! nul é, tecnicamente

1344
01:07:40,773 --> 01:07:42,190
>o que está armazenado embaixo do capô.
1345
01:07:42,190 --> 01:07:45,250
>Mas, qual é a duração do Hi! ?

1346
01:07:45,250 --> 01:07:48,070
>Bem, as probabilidades são, no mundo
humano, é HI!.

1347
01:07:48,070 --> 01:07:50,710
>E quem se importa com esse detalhe
de baixo nível, esse terminador nul.

1348
01:07:50,710 --> 01:07:53,800
>Você não inclui isso no comprimento de uma
palavra em inglês ou de qualquer palavra.

1349
01:07:53,800 --> 01:07:56,290
>Você só pensa nos caracteres
reais que pode ver.

1350
01:07:56,290 --> 01:08:00,580
>Portanto, o comprimento de H, i,
ponto de exclamação, é 3.

1351
01:08:00,580 --> 01:08:08,110
>Mas eu preciso habilmente adicionar mais um bite,
um quarto, para o caractere nulo,

1352
01:08:08,110 --> 01:08:10,580
>porque terei que
copiá-lo também.

1353
01:08:10,580 --> 01:08:13,270
>Caso contrário, se eu não tiver
um caractere nul idêntico,

1354
01:08:13,270 --> 01:08:15,830
>não vai ter um
final óbvio.

1355
01:08:15,830 --> 01:08:17,872
>Então, como faço para copiar, agora,
uma string na outra?

1356
01:08:17,872 --> 01:08:20,538
>Bem, agora eu vou recorrer ao
nosso velho amigo, o loop for,
1357
01:08:20,538 --> 01:08:21,380
>da primeira semana.

1358
01:08:21,380 --> 01:08:24,050
>E digamos, for i = 0 -

1359
01:08:24,050 --> 01:08:26,810
>que tal, na verdade, n é igual
ao comprimento da string de s.

1360
01:08:26,810 --> 01:08:28,279
>Já fizemos esse truque antes.

1361
01:08:28,279 --> 01:08:33,080
>i é menor que n, i ++.

1362
01:08:33,080 --> 01:08:38,689
>Eu vou, simplesmente,
dizer t [i] gets s[i].

1363
01:08:38,689 --> 01:08:43,939
>Então, isso irá copiar de s,
cada um dos caracteres, um de cada vez

1364
01:08:43,939 --> 01:08:45,020
>em t.

1365
01:08:45,020 --> 01:08:46,640
>Mas preciso ser um pouco mais esperto agora.

1366
01:08:46,640 --> 01:08:49,130
>Embora quase sempre
façamos i<n,

1367
01:08:49,130 --> 01:08:55,660
>na verdade, vou dizer de forma muito
agressiva i <= n.

1368
01:08:55,660 --> 01:08:56,830
>Por quê?

1369
01:08:56,830 --> 01:09:00,250
>Por que vou um passo além
do que normalmente considero

1370
01:09:00,250 --> 01:09:03,310
>fazer ao iterar sobre strings,
e um passo além do que você

1371
01:09:03,310 --> 01:09:07,149
>provavelmente faria ao iterar sobre
uma cifra de césar ou uma string

1372
01:09:07,149 --> 01:09:09,130
>nesse contexto?

1373
01:09:09,130 --> 01:09:10,939
>Brian, alguma ideia aqui?

1374
01:09:10,939 --> 01:09:16,569
>Por que vou de i menor ou igual
a n, mais ou menos pela primeira vez aqui?

1375
01:09:16,569 --> 01:09:19,779
>BRIAN: Celina está sugerindo que
precisamos incluir o caractere nul.

1376
01:09:19,779 --> 01:09:22,843
>DAVID MALAN: Sim, então se eu-- e agora
eu entendo como as strings funcionam.

1377
01:09:22,843 --> 01:09:25,510
>Portanto, não é suficiente apenas
copiar H,I,!

1378
01:09:25,510 --> 01:09:29,020
>Preciso dar um passo adiante, mais
um do que o comprimento da string.

1379
01:09:29,020 --> 01:09:32,290
>E a maneira mais fácil de fazer
isso seria menor ou igual a n.

1380
01:09:32,290 --> 01:09:34,450
>Ou eu poderia simplesmente fazer um +1 ali.

1381
01:09:34,450 --> 01:09:35,950
>Ou posso fazer isso de várias maneiras.

1382
01:09:35,950 --> 01:09:37,399
>Não importa como você faz isso.
1383
01:09:37,399 --> 01:09:40,899
>Mas acho que menor ou igual a é uma
maneira razoável de fazer isso.

1384
01:09:40,899 --> 01:09:43,540
>E agora, vamos descer ao
fundo aqui e agora

1385
01:09:43,540 --> 01:09:44,590
>faço esta conversão em maiúscula.

1386
01:09:44,590 --> 01:09:47,710
>Vamos agora mudar o
primeiro caractere em t

1387
01:09:47,710 --> 01:09:52,750
>para ser o resultado de to upper
do primeiro caractere de t.

1388
01:09:52,750 --> 01:09:56,770
>E então, como antes, vamos
imprimir o que quer que seja.

1389
01:09:56,770 --> 01:09:59,080
>E como antes, vamos
prosseguir e imprimir

1390
01:09:59,080 --> 01:10:05,110
>seja o que t for e espero que agora
t tenha sido convertido em maiúscula.

1391
01:10:05,110 --> 01:10:07,330
>Mas preciso fazer uma mudança agora.

1392
01:10:07,330 --> 01:10:10,690
>Acontece que esta
função, malloc, vem

1393
01:10:10,690 --> 01:10:12,897
>em um arquivo denominado lib ponto h, padrão.

1394
01:10:12,897 --> 01:10:15,730
>E, novamente, esse é o tipo de
coisa que você pode anotar.

1395
01:10:15,730 --> 01:10:17,563
>Você sempre pode pesquisar
esse tipo de coisa no Google.

1396
01:10:17,563 --> 01:10:20,740
>Até eu esqueço em quais arquivos de cabeçalho
essas funções às vezes são declaradas.

1397
01:10:20,740 --> 01:10:24,310
>Mas acontece de ser um novo chamado
lib padrão para biblioteca

1398
01:10:24,310 --> 01:10:26,110
>que dá acesso ao malloc.

1399
01:10:26,110 --> 01:10:29,800
>Então deixe-me ir em frente,
agora, fazer make compare.

1400
01:10:29,800 --> 01:10:31,210
>Tudo bem, até agora tudo bem.

1401
01:10:31,210 --> 01:10:34,360
>./compare - desculpe,
isso não é compare.

1402
01:10:34,360 --> 01:10:35,680
>O programa antigo funciona bem.

1403
01:10:35,680 --> 01:10:38,630
>Make copy - oh meu Deus, sete erros.

1404
01:10:38,630 --> 01:10:40,460
>O que eu fiz de errado aqui?

1405
01:10:40,460 --> 01:10:44,560
>Oh, parece que esqueci
o tipo de i e n.

1406
01:10:44,560 --> 01:10:47,440
>Então, deixe-me entrar em meu
loop for e adicionar o int.

1407
01:10:47,440 --> 01:10:49,870
>Isso foi minha culpa.
Vamos fazer uma cópia novamente.

1408
01:10:49,870 --> 01:10:51,910
>OK, todos os sete erros,
felizmente, sumiram.

1409
01:10:51,910 --> 01:10:56,710
>Make copy, vamos digitar hi!
em minúsculas e pressionar Enter.

1410
01:10:56,710 --> 01:11:02,860
>E pronto, agora coloquei em maiúscula
apenas a cópia de s, também conhecida como

1411
01:11:02,860 --> 01:11:03,580
>t.

1412
01:11:03,580 --> 01:11:06,010
>E só para ficar claro, eu
meio que regredi de volta

1413
01:11:06,010 --> 01:11:09,140
>à minha notação de colchetes, honestamente,
porque é perfeitamente aceitável.

1414
01:11:09,140 --> 01:11:10,360
>É muito legível.

1415
01:11:10,360 --> 01:11:12,640
>Mas observe, se eu
quero me exibir,

1416
01:11:12,640 --> 01:11:19,190
>eu poderia dizer algo como,
bem, vá para o local de t + i.

1417
01:11:19,190 --> 01:11:23,078
>E então faça isso, o que, novamente, não
necessariamente recomendo, para facilitar a leitura.

1418
01:11:23,078 --> 01:11:24,620
>Mas, novamente, existe essa equivalência.

1419
01:11:24,620 --> 01:11:28,640
>A notação de colchetes é a mesma
coisa que a operação matemática de ponteiro.

1420
01:11:28,640 --> 01:11:34,160
>Então, se você quiser ir para o endereço
em t mais o que for i para se compensar

1421
01:11:34,160 --> 01:11:36,570
>um ou mais bytes, você pode
fazer isso sem problemas.

1422
01:11:36,570 --> 01:11:39,920
>E se eu quiser ser sofisticado,
eu posso descer aqui e dizer,

1423
01:11:39,920 --> 01:11:45,350
>vá para o primeiro caractere
em t e coloque-o em maiúscula.

1424
01:11:45,350 --> 01:11:48,170
>Mas, novamente, eu diria que, embora,
sim, você seja muito inteligente

1425
01:11:48,170 --> 01:11:50,420
>e que você entende as dicas
e endereços neste momento

1426
01:11:50,420 --> 01:11:51,795
>se você estiver escrevendo um código assim.

1427
01:11:51,795 --> 01:11:53,990
>Honestamente, não é
necessariamente legível.

1428
01:11:53,990 --> 01:11:57,800
>Então, continuando com a sintaxe da semana
dois da notação de colchetes, totalmente

1429
01:11:57,800 --> 01:12:03,110
>razoável, totalmente correto, totalmente
bem projetado e talvez preferível,

1430
01:12:03,110 --> 01:12:04,890
>embora eu deva ter cuidado aqui.

1431
01:12:04,890 --> 01:12:07,550
>Esta linha de código é um
pouco arriscada para mim

1432
01:12:07,550 --> 01:12:10,310
>porque e se o usuário apenas
clicar em Enter e não digitar hi
1433
01:12:10,310 --> 01:12:11,540
>ou David ou Brian.

1434
01:12:11,540 --> 01:12:13,580
>E se não digitarem nada, exceto Enter?

1435
01:12:13,580 --> 01:12:16,130
>Nesse caso, o comprimento
da string pode ser 0.

1436
01:12:16,130 --> 01:12:19,220
>E então eu provavelmente não deveria
colocar o primeiro caractere em maiúscula

1437
01:12:19,220 --> 01:12:22,230
>em uma string que
nem existe.

1438
01:12:22,230 --> 01:12:25,250
>Então, provavelmente devo ter
alguma verificação de erros,

1439
01:12:25,250 --> 01:12:32,450
>como se, por exemplo, o comprimento da
string de t for pelo menos maior que 0,

1440
01:12:32,450 --> 01:12:34,960
>então vá em frente e faça isso com segurança.

1441
01:12:34,960 --> 01:12:37,550
>Mas, novamente, este é um
exemplo de algum erro adicional

1442
01:12:37,550 --> 01:12:39,200
>verificando se posso adicionar ao programa.

1443
01:12:39,200 --> 01:12:41,300
>Na verdade, há mais uma
verificação de erro

1444
01:12:41,300 --> 01:12:43,520
>que eu deveria fazer em
um programa totalmente correto,

1445
01:12:43,520 --> 01:12:45,170
>como você deve fazer em conjuntos de problemas.

1446
01:12:45,170 --> 01:12:47,010
>Às vezes, as coisas podem dar errado.

1447
01:12:47,010 --> 01:12:50,270
>E se o seu programa for tão grande,
tão extravagante, e tão faminto por memória

1448
01:12:50,270 --> 01:12:52,187
>que você está usando o comando malloc
e usando muita e muita memória,

1449
01:12:52,187 --> 01:12:54,062
>que você não fará no
programa tão pequeno,

1450
01:12:54,062 --> 01:12:56,270
>mas com o tempo você pode
precisar de mais e mais memória,

1451
01:12:56,270 --> 01:13:01,490
>também devemos ter certeza de que t
tem um endereço válido.

1452
01:13:01,490 --> 01:13:04,670
>Acontece que malloc,
na maioria das vezes,

1453
01:13:04,670 --> 01:13:08,090
>vai devolver para você o
endereço de um pedaço de memória

1454
01:13:08,090 --> 01:13:09,470
>alocado para você.

1455
01:13:09,470 --> 01:13:11,300
>Assim como get string,
vai voltar para você

1456
01:13:11,300 --> 01:13:14,900
>o endereço do primeiro
byte do pedaço de memória

1457
01:13:14,900 --> 01:13:16,820
>para o qual encontrou espaço.
1458
01:13:16,820 --> 01:13:18,740
>No entanto, às vezes as coisas podem dar errado.

1459
01:13:18,740 --> 01:13:20,630
>Às vezes, seu computador
pode estar sem memória.

1460
01:13:20,630 --> 01:13:24,320
>Você provavelmente já viu seu Mac ou
O PC congelar, travar ou reiniciar sozinho.

1461
01:13:24,320 --> 01:13:26,910
>Isso geralmente é o resultado
de erros de memória.

1462
01:13:26,910 --> 01:13:29,000
>Portanto, devemos
verificar algo assim.

1463
01:13:29,000 --> 01:13:32,570
>Se t for igual a este
valor especial nul,

1464
01:13:32,570 --> 01:13:35,360
>então vou
apenas pular e devolver um,

1465
01:13:35,360 --> 01:13:37,280
>e sair,
vamos sair do programa.

1466
01:13:37,280 --> 01:13:38,760
>Não vai funcionar.

1467
01:13:38,760 --> 01:13:41,610
>Isso pode acontecer apenas
uma em um milhão de vezes.

1468
01:13:41,610 --> 01:13:44,220
>Mas é mais correto verificar se há nul.

1469
01:13:44,220 --> 01:13:48,350
>Agora, infelizmente, os designers de
C meio que usaram - ou programadores

1470
01:13:48,350 --> 01:13:53,210
>mais geralmente, esta palavra,
que é quase o mesmo que N-U-L,

1471
01:13:53,210 --> 01:13:54,980
>também conhecida como \0.

1472
01:13:54,980 --> 01:13:57,290
>Infelizmente, esse é
um valor diferente.

1473
01:13:57,290 --> 01:14:01,370
>N-U-L-L representa um ponteiro nul.

1474
01:14:01,370 --> 01:14:02,870
>É um endereço falso.

1475
01:14:02,870 --> 01:14:04,580
>É a ausência de endereço.

1476
01:14:04,580 --> 01:14:06,950
>Tecnicamente, seu endereço é 0.

1477
01:14:06,950 --> 01:14:09,230
>É diferente de \ 0.

1478
01:14:09,230 --> 01:14:14,000
>Você usa N-U-L-L no contexto de
ponteiros, como estamos fazendo hoje.

1479
01:14:14,000 --> 01:14:17,390
>Você usa \ 0,
de outra forma conhecido verbalmente,

1480
01:14:17,390 --> 01:14:21,210
>como um N-U-L, ou nul, no
contexto de caracteres.

1481
01:14:21,210 --> 01:14:23,810
>Portanto, a \ 0 é para caracteres.

1482
01:14:23,810 --> 01:14:26,750
>N-U-L-L em maiúsculas é para ponteiros.

1483
01:14:26,750 --> 01:14:29,750
>E é um novo símbolo que
estamos apresentando hoje
1484
01:14:29,750 --> 01:14:34,520
>que vem com este arquivo
lib ponto h padrão.

1485
01:14:34,520 --> 01:14:38,190
>Tudo bem, então parece, honestamente,
que eu não preciso fazer parte desse trabalho.

1486
01:14:38,190 --> 01:14:41,610
>Acontece que se eu quiser
copiar uma string para outra,

1487
01:14:41,610 --> 01:14:43,170
>existe uma função para isso.

1488
01:14:43,170 --> 01:14:45,920
>E cada vez mais, você não terá que
escrever tantas linhas de código

1489
01:14:45,920 --> 01:14:49,520
>como você fez anteriormente, porque
se você olhar nas páginas de manual

1490
01:14:49,520 --> 01:14:52,730
>ou você ouviu falar ou descobriu
online que há outra função, como uma

1491
01:14:52,730 --> 01:14:56,790
>chamada strcpy, você pode, na verdade,
mais simplesmente, fazer algo assim.

1492
01:14:56,790 --> 01:15:00,410
>Embora eu tenha gostado da ideia,
e foi correto usar um loop for

1493
01:15:00,410 --> 01:15:04,950
>para copiar todos os caracteres de
s para t, há uma função para isso.

1494
01:15:04,950 --> 01:15:06,200
>É chamada de strcpy.

1495
01:15:06,200 --> 01:15:09,830
>Leva dois argumentos, o
destino seguido pela fonte.
1496
01:15:09,830 --> 01:15:12,200
>E vai lidar
com todo o looping

1497
01:15:12,200 --> 01:15:15,890
>para nós, todas as cópias para nós,
incluindo \ 0,

1498
01:15:15,890 --> 01:15:18,830
>para que eu possa me concentrar no
que quero fazer, que, neste caso,

1499
01:15:18,830 --> 01:15:21,300
>é, na verdade, converter em maiúscula as coisas.

1500
01:15:21,300 --> 01:15:26,497
>Então, se considerarmos, agora, este exemplo,
no contexto da memória do meu computador,

1501
01:15:26,497 --> 01:15:28,580
>veremos que é um
pouco diferente.

1502
01:15:28,580 --> 01:15:31,050
>Mas há mais um bug
que eu quero consertar primeiro.

1503
01:15:31,050 --> 01:15:33,230
>E isso é algo que ainda
não tivemos que fazer.

1504
01:15:33,230 --> 01:15:37,850
>Acontece que sempre que você
aloca memória com malloc,

1505
01:15:37,850 --> 01:15:41,330
>você pede memória ao computador,
a responsabilidade recai sobre você, o programador,

1506
01:15:41,330 --> 01:15:43,160
>para, eventualmente, devolvê-la.

1507
01:15:43,160 --> 01:15:46,070
>E com isso, quero dizer que
se você alocar quatro bytes,

1508
01:15:46,070 --> 01:15:49,430
>ou quem sabe, quatro milhões de bytes de
memória para um programa ainda maior,

1509
01:15:49,430 --> 01:15:52,160
>é melhor devolver o espaço ao computador,
mais especificamente,

1510
01:15:52,160 --> 01:15:55,252
>ao sistema operacional, seja
Linux ou Mac OS ou Windows,

1511
01:15:55,252 --> 01:15:57,710
>para que seu computador
não fique sem memória.

1512
01:15:57,710 --> 01:16:00,418
>Se tudo o que você faz é pedir
mais memória e mais memória,

1513
01:16:00,418 --> 01:16:03,710
>é lógico que, eventualmente, seu
computador ficará sem, porque ele apenas

1514
01:16:03,710 --> 01:16:05,370
>tem uma quantidade finita de memória.

1515
01:16:05,370 --> 01:16:07,910
>Ele tem uma quantidade finita
de hardware.

1516
01:16:07,910 --> 01:16:11,780
>Então, quando você terminar de usar
a memória, deve ser sua melhor prática

1517
01:16:11,780 --> 01:16:14,970
>liberá-la depois também.

1518
01:16:14,970 --> 01:16:18,950
>E o oposto de malloc é uma
função chamada free, que leva,

1519
01:16:18,950 --> 01:16:22,040
>como sua entrada, qualquer
que seja a saída de malloc.

1520
01:16:22,040 --> 01:16:25,070
>E lembre-se de que a saída de malloc,
o valor de retorno de malloc,

1521
01:16:25,070 --> 01:16:30,210
>é o endereço do primeiro byte
de memória que ele alocou para você.

1522
01:16:30,210 --> 01:16:34,010
>Então, se você pedir quatro bytes, como
eu fiz algumas linhas atrás com malloc,

1523
01:16:34,010 --> 01:16:37,100
>você receberá de volta o endereço
do primeiro desses bytes.

1524
01:16:37,100 --> 01:16:41,150
>E cabe a você lembrar
quantos bytes você pediu.

1525
01:16:41,150 --> 01:16:43,760
>No caso de free,
tudo o que tem a fazer é

1526
01:16:43,760 --> 01:16:49,820
>dizer free, por meio de sua entrada,
o endereço que o malloc lhe forneceu.

1527
01:16:49,820 --> 01:16:53,210
>Então, se você armazenou esse endereço como
eu fiz, nesta variável chamada t,

1528
01:16:53,210 --> 01:16:58,190
>é suficiente quando você termine
aquela memória com a chamada t free.

1529
01:16:58,190 --> 01:17:02,360
>E o computador irá liberar
essa memória para você.

1530
01:17:02,360 --> 01:17:04,880
>E você pode muito bem
recuperá-la mais tarde.

1531
01:17:04,880 --> 01:17:07,400
>Mas pelo menos o seu computador
não ficará sem memória

1532
01:17:07,400 --> 01:17:13,490
>tão rapidamente, porque agora ele pode
reutilizar esse espaço para outra coisa.

1533
01:17:13,490 --> 01:17:15,410
>Tudo bem, deixe-me ir em
frente, então, e propor

1534
01:17:15,410 --> 01:17:17,870
>que desenhemos uma imagem disso -

1535
01:17:17,870 --> 01:17:20,942
>agora a memória do novo programa,
onde copiamos as coisas.

1536
01:17:20,942 --> 01:17:23,900
>Então, lembre-se, foi aqui que paramos
antes ao comparar duas strings.

1537
01:17:23,900 --> 01:17:29,010
>Se este fosse s, apontando para
h, i, !, em minúsculas,

1538
01:17:29,010 --> 01:17:32,510
>esta nova versão do meu
código em copy.c, veja só,

1539
01:17:32,510 --> 01:17:34,550
>ainda me dá outro ponteiro chamado t.

1540
01:17:34,550 --> 01:17:36,530
>Portanto, essa parte
da história não mudou.

1541
01:17:36,530 --> 01:17:37,970
>Mas eu chamo malloc agora.

1542
01:17:37,970 --> 01:17:40,790
>E malloc vai me devolver
um novo pedaço de memória.

1543
01:17:40,790 --> 01:17:42,440
>Não sei de antemão onde está.

1544
01:17:42,440 --> 01:17:45,740
>Mas o valor de retorno de
malloc será o endereço
1545
01:17:45,740 --> 01:17:47,920
>do primeiro bite dessa memória.

1546
01:17:47,920 --> 01:17:51,050
>Então, por exemplo, 0x456
ou seja o que for.

1547
01:17:51,050 --> 01:17:54,230
>E os bytes subsequentes
vão aumentar em um

1548
01:17:54,230 --> 01:17:59,630
>byte de cada vez, 0x457, 0x458, 0x459.

1549
01:17:59,630 --> 01:18:03,800
>Então, o que é, em última análise, armazenado em t quando
eu atribuo a ele o valor de retorno de malloc?

1550
01:18:03,800 --> 01:18:05,570
>É o que quer que seja esse endereço.

1551
01:18:05,570 --> 01:18:07,980
>Novamente, eu poderia escrever
tecnicamente 0x456 aqui.

1552
01:18:07,980 --> 01:18:09,800
>Mas, novamente, já superamos isso.

1553
01:18:09,800 --> 01:18:10,970
>Isso foi há 30 minutos.

1554
01:18:10,970 --> 01:18:14,300
>Agora vamos nos concentrar apenas
na abstração que é um ponteiro.

1555
01:18:14,300 --> 01:18:17,690
>Um ponteiro é uma seta
apontando a partir da variável

1556
01:18:17,690 --> 01:18:19,980
>para o local real na memória.

1557
01:18:19,980 --> 01:18:26,720
>Então agora, se eu for copiar s para t
usando strcpy, ou mais manualmente,
1558
01:18:26,720 --> 01:18:28,670
>usando meu loop for, o que acontece?

1559
01:18:28,670 --> 01:18:31,610
>Bem, estou copiando
h de s para t.

1560
01:18:31,610 --> 01:18:36,110
>Estou copiando o i de s para t,
o ponto de exclamação de s para t.

1561
01:18:36,110 --> 01:18:40,530
>E, por último, o caractere nul
de terminação de s para t.

1562
01:18:40,530 --> 01:18:42,740
>Portanto, a imagem agora é
fundamentalmente diferente.

1563
01:18:42,740 --> 01:18:45,020
>t não está apontando para a mesma coisa.

1564
01:18:45,020 --> 01:18:50,570
>Está apontando para seu próprio pedaço
de memória que agora, um passo de cada vez,

1565
01:18:50,570 --> 01:18:56,210
>duplicando tudo o que
estava no endereço s.

1566
01:18:56,210 --> 01:18:59,600
>E isso é o que você e eu, como humanos,
consideraríamos, presumivelmente,

1567
01:18:59,600 --> 01:19:04,080
>ser uma cópia adequada do programa.

1568
01:19:04,080 --> 01:19:09,660
>Alguma dúvida, então, sobre o que acabamos de
fazer com a introdução do malloc e do free?

1569
01:19:09,660 --> 01:19:11,910
>O primeiro deles aloca
memória e dá a você

1570
01:19:11,910 --> 01:19:15,750
>o endereço do primeiro byte de
memória que você pode usar agora,

1571
01:19:15,750 --> 01:19:19,260
>o último o devolve ao seu
sistema operacional e diz:

1572
01:19:19,260 --> 01:19:20,700
>terminei com isso.

1573
01:19:20,700 --> 01:19:24,360
>Agora pode ser reutilizado para
outra coisa, alguma outra variável,

1574
01:19:24,360 --> 01:19:27,090
>talvez, no futuro, se nosso
programa fosse mais longo.

1575
01:19:27,090 --> 01:19:31,530
>Brian, alguma dúvida ou
confusão em que posso ajudar?

1576
01:19:31,530 --> 01:19:33,870
>BRIAN: Alguém perguntou, mesmo
se você estiver usando strcpy

1577
01:19:33,870 --> 01:19:37,470
>para copiar a string em vez de copiar
os caracteres um de cada vez,

1578
01:19:37,470 --> 01:19:39,420
>você ainda precisa liberar a memória?

1579
01:19:39,420 --> 01:19:40,545
>DAVID MALAN: Boa pergunta.

1580
01:19:40,545 --> 01:19:43,320
>Mesmo se você estiver usando strcpy,
você ainda precisa usar free.

1581
01:19:43,320 --> 01:19:48,120
>Sim, a partir de agora, sempre que você
usar o malloc, deverá usar free.

1582
01:19:48,120 --> 01:19:52,470
>Sempre que usar malloc, você deve
usar free para liberar essa memória.

1583
01:19:52,470 --> 01:19:56,370
>strcpy está copiando o conteúdo de
um pedaço de memória para o outro.

1584
01:19:56,370 --> 01:19:59,220
>Ele não está alocando ou gerenciando
essa memória para você.

1585
01:19:59,220 --> 01:20:02,520
>Está apenas implementando,
isso para loop.

1586
01:20:02,520 --> 01:20:05,520
>E talvez seja a hora de tirar
outra roda de treinamento

1587
01:20:05,520 --> 01:20:06,020
>verbalmente.

1588
01:20:06,020 --> 01:20:10,410
>Acontece que get string,
todo esse tempo, é meio mágico.

1589
01:20:10,410 --> 01:20:13,470
>Uma das coisas que get string
faz a partir da biblioteca CS50

1590
01:20:13,470 --> 01:20:16,080
>é que ele próprio usa malloc.

1591
01:20:16,080 --> 01:20:19,800
>Considere, afinal, quando nós, o staff,
escrevemos get string anos atrás,

1592
01:20:19,800 --> 01:20:22,830
>não tínhamos ideia de quanto tempo
seus nomes vão durar este ano.

1593
01:20:22,830 --> 01:20:24,690
>Não temos ideia de quais
frases você está falando

1594
01:20:24,690 --> 01:20:28,350
>para digitar, quais parágrafos você vai
digitar, que texto você vai analisar
1595
01:20:28,350 --> 01:20:30,240
>para um programa como readability.

1596
01:20:30,240 --> 01:20:32,610
>Então, tivemos que implementar
get string de tal forma

1597
01:20:32,610 --> 01:20:35,730
>que você pode digitar poucos ou
tantos caracteres em seu teclado

1598
01:20:35,730 --> 01:20:36,420
>como você quiser.

1599
01:20:36,420 --> 01:20:40,150
>E vamos garantir que haja memória
suficiente para essa string.

1600
01:20:40,150 --> 01:20:43,530
>Então, get string, por baixo do capô,
se você olhar para o código, nós, o staff,

1601
01:20:43,530 --> 01:20:46,530
>escrevemos algum dia, você
verá que usamos malloc.

1602
01:20:46,530 --> 01:20:51,390
>E chamamos malloc para obter memória
suficiente para caber nessa string.

1603
01:20:51,390 --> 01:20:54,600
>E então, o que a biblioteca CS50
também está secretamente fazendo,

1604
01:20:54,600 --> 01:20:57,060
>é que também está chamando free para você.

1605
01:20:57,060 --> 01:20:59,130
>Há um jeito sofisticado onde você

1606
01:20:59,130 --> 01:21:03,690
>pode escrever um programa que, assim que o
main estiver prestes a sair ou retornar

1607
01:21:03,690 --> 01:21:06,480
>para o seu prompt piscando,
algum código especial

1608
01:21:06,480 --> 01:21:10,860
>nós escrevemos swoops naquele momento
final, liberando qualquer parte da memória

1609
01:21:10,860 --> 01:21:14,130
>que nós, a biblioteca,
alocamos para que você

1610
01:21:14,130 --> 01:21:17,190
>não fique sem memória por nossa causa.

1611
01:21:17,190 --> 01:21:19,590
>Mas todos vocês, ao
usar malloc, terão

1612
01:21:19,590 --> 01:21:23,700
>que chamar free, porque a
biblioteca não vai fazer isso por você.

1613
01:21:23,700 --> 01:21:26,400
>E, a meta de hoje
e da próxima semana e além

1614
01:21:26,400 --> 01:21:30,833
>é parar de usar a biblioteca CS50,
em última análise, por completo.

1615
01:21:30,833 --> 01:21:33,000
>Tudo bem, vamos-- seria
injusto, eu acho,

1616
01:21:33,000 --> 01:21:36,000
>se introduzirmos todas essas novas técnicas
sofisticadas, mas não necessariamente

1617
01:21:36,000 --> 01:21:40,620
>fornecemos a você qualquer tipo de ferramenta
para determinar a perseguição de bugs

1618
01:21:40,620 --> 01:21:43,245
>em seu novo código sofisticado
ou resolução de problemas, agora,

1619
01:21:43,245 --> 01:21:44,370
>que estão relacionados à memória.

1620
01:21:44,370 --> 01:21:46,860
>E, felizmente, existem
programas por meio dos quais

1621
01:21:46,860 --> 01:21:49,560
>você pode perseguir bugs relacionados à memória.

1622
01:21:49,560 --> 01:21:52,080
>Isso é além de printf,

1623
01:21:52,080 --> 01:21:56,550
>e help50 e check50 e debug50 e
depuradores de forma mais geral.

1624
01:21:56,550 --> 01:21:59,940
>Este programa - e é a última das
novas ferramentas que apresentaremos a você

1625
01:21:59,940 --> 01:22:01,920
>em C-- é chamado valgrind.

1626
01:22:01,920 --> 01:22:04,830
>E este é um programa que
existe no CS50 IDE.

1627
01:22:04,830 --> 01:22:07,620
>Mas existe em Macs e
PCs e Linux

1628
01:22:07,620 --> 01:22:10,050
>em qualquer lugar, onde você pode
executá-lo em seu código

1629
01:22:10,050 --> 01:22:12,870
>para detectar se você está fazendo
algo errado com a memória.

1630
01:22:12,870 --> 01:22:14,370
>O que você pode fazer de errado com a memória?

1631
01:22:14,370 --> 01:22:17,037
>Bem, antes, lembre-se, eu acionei
essa falha de segmentação.

1632
01:22:17,037 --> 01:22:19,320
>Toquei a memória que não deveria.

1633
01:22:19,320 --> 01:22:22,080
>Valgrind é uma ferramenta que
pode ajudá-lo a descobrir,

1634
01:22:22,080 --> 01:22:25,000
>onde você tocou na
memória que não deveria,

1635
01:22:25,000 --> 01:22:27,960
>de modo a focar sua própria atenção
humana em quaisquer linhas de código

1636
01:22:27,960 --> 01:22:28,830
>que pode estar cheio de erros.

1637
01:22:28,830 --> 01:22:32,610
>Valgrind grant também pode detectar se
você esquecer de chamar free.

1638
01:22:32,610 --> 01:22:36,240
>Se você chamar malloc uma ou
mais vezes, mas não chamar free

1639
01:22:36,240 --> 01:22:38,280
>um número correspondente
de vezes, valgrind

1640
01:22:38,280 --> 01:22:40,890
>é um programa que pode perceber
isso e dizer que você tem

1641
01:22:40,890 --> 01:22:42,580
>o que é chamado de vazamento de memória.

1642
01:22:42,580 --> 01:22:44,760
>E, isso é pertinente
aos nossos próprios Macs e PCs.

1643
01:22:44,760 --> 01:22:47,100
>Novamente, se você tem usado
o seu Mac ou PC ou às vezes

1644
01:22:47,100 --> 01:22:50,070
>até mesmo seu telefone por
muito, muito tempo, e talvez

1645
01:22:50,070 --> 01:22:53,340
>executando muitos programas diferentes ao
mesmo tempo, muitas guias do navegador

1646
01:22:53,340 --> 01:22:55,680
>abertas, muitos programas
diferentes abertos ao mesmo tempo,

1647
01:22:55,680 --> 01:22:59,370
>seu Mac ou PC pode muito bem
ter começado a ficar lento.

1648
01:22:59,370 --> 01:23:01,920
>Pode ser irritante, se
não impossível de usar,

1649
01:23:01,920 --> 01:23:03,960
>porque tudo é muito lento.

1650
01:23:03,960 --> 01:23:07,920
>Isso pode muito bem ser porque um ou
mais dos programas que você está usando

1651
01:23:07,920 --> 01:23:12,480
>tem algum bug em que um programador
ficava alocando memória

1652
01:23:12,480 --> 01:23:15,210
>e nunca chamou free.

1653
01:23:15,210 --> 01:23:17,273
>Talvez seja um bug, talvez
tenha sido deliberado,

1654
01:23:17,273 --> 01:23:19,440
>não esperavam que você
tivesse tantas janelas abertas.

1655
01:23:19,440 --> 01:23:21,360
>Mas o valgrind pode
detectar erros como esse.

1656
01:23:21,360 --> 01:23:23,730
>E honestamente, alguns de
vocês, se forem como eu,
1657
01:23:23,730 --> 01:23:29,370
>você pode muito bem ter 10, 20, 50 guias
diferentes do navegador abertas ao mesmo tempo,

1658
01:23:29,370 --> 01:23:32,910
>pensando "eu vou voltar a isso algum dia",
embora nunca o façamos.

1659
01:23:32,910 --> 01:23:34,950
>Cada uma dessas guias ocupa memória.

1660
01:23:34,950 --> 01:23:37,320
>Literalmente, sempre que você abrir
uma guia do navegador, pense nisso,

1661
01:23:37,320 --> 01:23:41,580
>como Chrome ou Edge ou Firefox
ou qualquer outro

1662
01:23:41,580 --> 01:23:43,920
>que você está usando, por
baixo do capô, estão

1663
01:23:43,920 --> 01:23:46,320
>provavelmente chamando uma
função no Mac OS ou Windows

1664
01:23:46,320 --> 01:23:50,670
>como malloc para lhe dar mais memória para
conter o conteúdo dessa página da web

1665
01:23:50,670 --> 01:23:51,480
>temporariamente.

1666
01:23:51,480 --> 01:23:54,310
>E se você continuar abrindo
mais e mais guias do navegador,

1667
01:23:54,310 --> 01:23:56,190
>é como chamar malloc,
malloc, malloc.

1668
01:23:56,190 --> 01:23:57,840
>Eventualmente, você vai ficar sem recursos.

1669
01:23:57,840 --> 01:23:59,700
>E os computadores podem ser
inteligentes hoje em dia.

1670
01:23:59,700 --> 01:24:03,060
>Eles podem remover coisas temporariamente
da memória para liberar espaço.

1671
01:24:03,060 --> 01:24:04,477
>Isso é chamado de memória virtual.

1672
01:24:04,477 --> 01:24:06,310
>Mas, eventualmente,
algo vai sair mal.

1673
01:24:06,310 --> 01:24:08,520
>E pode muito bem ser sua
experiência de usuário

1674
01:24:08,520 --> 01:24:11,700
>quando as coisas ficam tão lentas que você
literalmente tem que sair do programa

1675
01:24:11,700 --> 01:24:14,140
>ou talvez até reiniciar o seu computador.

1676
01:24:14,140 --> 01:24:15,240
>Então, como usamos valgrind?

1677
01:24:15,240 --> 01:24:17,430
>Bem, vou escrever um pequeno programa

1678
01:24:17,430 --> 01:24:20,040
>que não faz nada de útil,
mas demonstra

1679
01:24:20,040 --> 01:24:22,080
>vários erros relacionados à memória.

1680
01:24:22,080 --> 01:24:24,060
>Vou chamar esse arquivo de memory.c.

1681
01:24:24,060 --> 01:24:27,550
>Vou prosseguir e abrir
o arquivo memory.c

1682
01:24:27,550 --> 01:24:30,842
>e incluir no topo o
padrão io ponto h.

1683
01:24:30,842 --> 01:24:32,550
>E então eu irei também,
preventivamente,

1684
01:24:32,550 --> 01:24:37,290
>incluir lib ponto h padrão, que
lembra de malloc, int main void.

1685
01:24:37,290 --> 01:24:39,070
>E vou manter tudo bem simples.

1686
01:24:39,070 --> 01:24:42,370
>Eu vou seguir em frente e criar
um monte de números inteiros.

1687
01:24:42,370 --> 01:24:43,810
>Então isso é legal.

1688
01:24:43,810 --> 01:24:46,480
>Acontece que--

1689
01:24:46,480 --> 01:24:47,880
>bem, vamos em frente.

1690
01:24:47,880 --> 01:24:48,910
>Sim, posso fazer isso.

1691
01:24:48,910 --> 01:24:50,035
>Vamos fazer isso.

1692
01:24:50,035 --> 01:24:52,650
>Char s* gets malloc.

1693
01:24:52,650 --> 01:24:57,630
>Agora eu vou criar, que tal três desses.

1694
01:24:57,630 --> 01:25:01,050
>Vou alocar espaço
para três caracteres.

1695
01:25:01,050 --> 01:25:03,640
>Ou, na verdade, vamos criar quatro,
como antes.

1696
01:25:03,640 --> 01:25:08,340
>Agora, vou prosseguir e dizer
que s colchete 0 é igual a 72.

1697
01:25:08,340 --> 01:25:12,220
>s colchete 1-- na verdade,
vou apenas fazer isso manualmente.

1698
01:25:12,220 --> 01:25:14,160
>Vamos fazer h.

1699
01:25:14,160 --> 01:25:16,350
>Vamos fazer i.

1700
01:25:16,350 --> 01:25:19,960
>Vamos fazer nosso ponto de exclamação usual.

1701
01:25:19,960 --> 01:25:22,170
>E então, apenas para garantir,
s colchete 3 gets

1702
01:25:22,170 --> 01:25:24,120
>"\ 0".

1703
01:25:24,120 --> 01:25:29,340
>Esta é a maneira muito
manual de -

1704
01:25:29,340 --> 01:25:32,430
>esta é a maneira muito manual de
construir uma string.

1705
01:25:32,430 --> 01:25:34,060
>Mas deixe-me apresentar um erro.

1706
01:25:34,060 --> 01:25:37,320
>Vamos alocar acidentalmente
apenas três bytes,

1707
01:25:37,320 --> 01:25:40,440
>embora eu claramente precise de um quarto
para aquele caractere nul final.

1708
01:25:40,440 --> 01:25:42,510
>E observe também a ausência de free.

1709
01:25:42,510 --> 01:25:45,720
>Eu vou, muito descuidadamente,
não me preocupar em chamar free.

1710
01:25:45,720 --> 01:25:49,590
>Agora, vou compilar este
programa, make memory.

1711
01:25:49,590 --> 01:25:53,430
>OK, ele compila OK, então isso
é bom, ./memory

1712
01:25:53,430 --> 01:25:55,413
>OK, nada acontece,
mas isso faz

1713
01:25:55,413 --> 01:25:57,330
>sentido porque eu não disse
a ele para fazer nada.

1714
01:25:57,330 --> 01:26:01,360
>Só por diversão, vamos imprimir
essa string como sempre fazemos.

1715
01:26:01,360 --> 01:26:04,500
>Vamos recompilar a memória,
ainda compila.

1716
01:26:04,500 --> 01:26:06,360
>Vamos executar ./memory.

1717
01:26:06,360 --> 01:26:07,570
>OK, parece funcionar.

1718
01:26:07,570 --> 01:26:10,000
>Portanto, à primeira vista, você pode
estar muito orgulhoso de si mesmo.

1719
01:26:10,000 --> 01:26:12,910
>Você escreveu outro programa correto,
parece passar no check50.

1720
01:26:12,910 --> 01:26:13,410
>Você submete.
1721
01:26:13,410 --> 01:26:14,327
>Você continua seu dia.

1722
01:26:14,327 --> 01:26:16,380
>E você fica muito desapontado
alguns dias depois

1723
01:26:16,380 --> 01:26:19,920
>quando você percebe, caramba, eu não
recebi todo o crédito nisso porque há

1724
01:26:19,920 --> 01:26:21,780
>na verdade, um bug evidente.

1725
01:26:21,780 --> 01:26:24,780
>Então, às vezes,
existem bugs no seu código

1726
01:26:24,780 --> 01:26:27,420
>que você não necessariamente vê,
visualmente, você não necessariamente

1727
01:26:27,420 --> 01:26:30,990
>experiencia ao executá-lo sozinho,
mas, eventualmente,

1728
01:26:30,990 --> 01:26:33,443
>pode aparecer um erro ao
executá-lo várias vezes.

1729
01:26:33,443 --> 01:26:36,360
>Eventualmente, um computador pode perceber
que você está fazendo algo errado.

1730
01:26:36,360 --> 01:26:38,460
>E, felizmente, existem
ferramentas como valgrind,

1731
01:26:38,460 --> 01:26:40,098
>que pode permitir que você detecte isso.

1732
01:26:40,098 --> 01:26:43,140
>Eu vou aumentar o tamanho
da janela do meu terminal aqui.

1733
01:26:43,140 --> 01:26:48,090
>Agora eu vou executar
o valgrind em ./memory.

1734
01:26:48,090 --> 01:26:49,290
>Portanto, é como debug50.

1735
01:26:49,290 --> 01:26:53,040
>Em vez de executar debug50 e, em seguida,
./ seja qual for o programa,

1736
01:26:53,040 --> 01:26:55,813
>você executa valgrind ./ memory.

1737
01:26:55,813 --> 01:26:58,230
>Esta, infelizmente, é uma
interface de linha de comando.

1738
01:26:58,230 --> 01:27:00,480
>Não há interface gráfica
do usuário como debug50.

1739
01:27:00,480 --> 01:27:04,530
>E, honestamente, é uma
sequência horrível de saída.

1740
01:27:04,530 --> 01:27:06,630
>Isso deve surpreendê-lo
à primeira vista.

1741
01:27:06,630 --> 01:27:08,190
>Há um visual codificado muito ruim.

1742
01:27:08,190 --> 01:27:09,690
>Não é o programa mais bem projetado.

1743
01:27:09,690 --> 01:27:12,520
>Foi feito para as
pessoas mais adaptadas à programação.

1744
01:27:12,520 --> 01:27:15,180
>Mas existem algumas dicas úteis
que podemos tirar disso.

1745
01:27:15,180 --> 01:27:17,490
>Como sempre, deixe-me mostrar
todo o caminho até o topo
1746
01:27:17,490 --> 01:27:19,260
>para a primeira linha de saída.

1747
01:27:19,260 --> 01:27:21,600
>E vou chamar sua atenção
para algumas coisas

1748
01:27:21,600 --> 01:27:23,070
>que vão começar a saltar aos
olhos para você.

1749
01:27:23,070 --> 01:27:24,960
>E help50 pode ajudá-lo com isso.

1750
01:27:24,960 --> 01:27:28,020
>Se você está confuso com a saída
de valgrind, execute-o novamente.

1751
01:27:28,020 --> 01:27:29,520
>Mas coloque help50 no início.

1752
01:27:29,520 --> 01:27:32,120
>E assim como farei agora
verbalmente, help50

1753
01:27:32,120 --> 01:27:36,510
>vai ajudá-lo a perceber as coisas importantes
nesta bagunça maluca de saída.

1754
01:27:36,510 --> 01:27:37,770
>Isso é preocupante.

1755
01:27:37,770 --> 01:27:41,880
>Valgrind está observando nesta linha
aqui, direito inválido de tamanho 1.

1756
01:27:41,880 --> 01:27:44,370
>E isso está na linha 10 de memory.c.

1757
01:27:44,370 --> 01:27:46,510
>Então, veremos isso em um momento.

1758
01:27:46,510 --> 01:27:50,530
>Se eu rolar mais para baixo,
leitura inválida de tamanho 1.
1759
01:27:50,530 --> 01:27:55,810
>E isso também parece estar aqui,
parece, na linha 11 de memory.c.

1760
01:27:55,810 --> 01:27:59,070
>E então, se eu continuar rolando,
continue rolando, continue rolando,

1761
01:27:59,070 --> 01:28:00,990
>Eu não estou gostando disso.

1762
01:28:00,990 --> 01:28:05,910
>3 bytes em 1 bloco são definitivamente perdidos
no registro de perda, seja ele qual for.

1763
01:28:05,910 --> 01:28:10,170
>Mas três bytes em 1 bloco estão
definitivamente perdidos.

1764
01:28:10,170 --> 01:28:15,240
>E então aqui embaixo, resumo do vazamento,
definitivamente perdido, 3 bytes em 1 blocos.

1765
01:28:15,240 --> 01:28:17,703
>Aliás, 1 blocos,
obviamente não é a gramática certa.

1766
01:28:17,703 --> 01:28:19,620
>Isso é o que acontece
quando seu programa não

1767
01:28:19,620 --> 01:28:24,210
>tem uma condição if que verifica
se o número é 1 ou positivo ou 0.

1768
01:28:24,210 --> 01:28:27,300
>Você poderia corrigir isso, gramaticalmente,
honestamente, com uma condição if simples.

1769
01:28:27,300 --> 01:28:29,770
>Eles não o fizeram quando escreveram
este programa anos atrás.

1770
01:28:29,770 --> 01:28:32,110
>Portanto, há dois ou três erros aqui.

1771
01:28:32,110 --> 01:28:34,620
>Um é algum tipo de leitura
ou gravação inválida.

1772
01:28:34,620 --> 01:28:35,953
>E outro é esse vazamento.

1773
01:28:35,953 --> 01:28:36,870
>Bem, o que é uma escrita?

1774
01:28:36,870 --> 01:28:38,940
>Uma gravação refere-se apenas à alteração de um valor.

1775
01:28:38,940 --> 01:28:43,150
>Uma leitura refere-se apenas à
leitura, uso ou impressão de um valor.

1776
01:28:43,150 --> 01:28:44,730
>Então, vamos nos concentrar na linha 10.

1777
01:28:44,730 --> 01:28:48,060
>Se eu rolar de volta para o meu
código e olhar a linha 10,

1778
01:28:48,060 --> 01:28:51,760
>esta foi uma gravação
inválida, gravação inválida.

1779
01:28:51,760 --> 01:28:52,950
>Bem, por que é inválido?

1780
01:28:52,950 --> 01:28:57,180
>Bem, pela definição de hoje,
se você estiver alocando 3 bytes,

1781
01:28:57,180 --> 01:29:01,710
>você pode tocar no primeiro byte,
o segundo byte e o terceiro byte.

1782
01:29:01,710 --> 01:29:04,500
>Mas você não tem que
tocar no quarto byte

1783
01:29:04,500 --> 01:29:06,420
>se você pediu apenas três.

1784
01:29:06,420 --> 01:29:11,070
>Isso é como uma versão em pequena escala
do muito aventureiro e inapropriado

1785
01:29:11,070 --> 01:29:14,100
>modo em que entrei, bisbilhotando,
quando olhei para 10.000 bytes adiante.

1786
01:29:14,100 --> 01:29:16,680
>Mesmo olhar a um byte de
distância é um bug em potencial

1787
01:29:16,680 --> 01:29:18,780
>e pode causar o travamento de um programa.

1788
01:29:18,780 --> 01:29:21,720
>Enquanto isso, a linha 11
também é problemática, o que

1789
01:29:21,720 --> 01:29:25,470
>é uma leitura inválida, porque agora,
você está dizendo para imprimir esta string.

1790
01:29:25,470 --> 01:29:28,043
>Mas essa string contém
um endereço de memória

1791
01:29:28,043 --> 01:29:30,210
>que você não deveria ter
tocado em primeiro lugar.

1792
01:29:30,210 --> 01:29:34,080
>E o vazamento de memória, o
terceiro problema, decorre do fato

1793
01:29:34,080 --> 01:29:36,520
>que não liberei essa memória.

1794
01:29:36,520 --> 01:29:40,380
>Então, novamente, vai precisar de alguma
prática e experiência, alguns erros seus,

1795
01:29:40,380 --> 01:29:42,480
>para perceber e entender esses bugs.

1796
01:29:42,480 --> 01:29:44,670
>Mas deixe-me corrigir os dois primeiros assim.
1797
01:29:44,670 --> 01:29:46,530
>Vou criar quatro bytes.

1798
01:29:46,530 --> 01:29:48,990
>E deixe-me consertar o
segundo ou o terceiro,

1799
01:29:48,990 --> 01:29:53,820
>ao liberar s bem no final,
porque, novamente, sempre que você usa malloc

1800
01:29:53,820 --> 01:29:55,590
>você deve usar free.

1801
01:29:55,590 --> 01:29:59,310
>Eu vou recompilar
a memória, parece compilar.

1802
01:29:59,310 --> 01:30:02,130
>Vamos executá-lo novamente, ainda
funciona da mesma forma, visualmente.

1803
01:30:02,130 --> 01:30:05,670
>Mas agora, vamos executar novamente o
valgrind nele e ver se há algum erro agora,

1804
01:30:05,670 --> 01:30:08,710
>então valgrind ./ memory, Enter.

1805
01:30:08,710 --> 01:30:10,710
>A saída ainda parecerá
muito enigmática.

1806
01:30:10,710 --> 01:30:15,300
>Mas observe que todos os blocos de heap foram
liberados, seja lá o que isso signifique.

1807
01:30:15,300 --> 01:30:16,217
>Nenhum vazamento é possível.

1808
01:30:16,217 --> 01:30:18,133
>Na verdade, não fica mais
explícito do que isso.

1809
01:30:18,133 --> 01:30:19,090
>Isso é uma coisa boa.

1810
01:30:19,090 --> 01:30:23,100
>E se eu rolar para cima, não vejo nenhuma
menção a essas leituras ou gravações inválidas.

1811
01:30:23,100 --> 01:30:26,168
>Então, começando com os problemas desta
semana e os da próxima semana em C,

1812
01:30:26,168 --> 01:30:27,960
>você não só vai querer
usar ferramentas

1813
01:30:27,960 --> 01:30:31,590
>como help50 e printf
e debug50 e check50,

1814
01:30:31,590 --> 01:30:35,710
>mas mesmo se você achar que seu código
está certo, a saída parece certa,

1815
01:30:35,710 --> 01:30:37,050
>você pode ter um bug latente.

1816
01:30:37,050 --> 01:30:40,200
>E mesmo quando seus programas são pequenos,
não travando o computador,

1817
01:30:40,200 --> 01:30:43,500
>Sem causar essa falha de
segmentação, eventualmente, eles vão.

1818
01:30:43,500 --> 01:30:47,850
>E é melhor usar ferramentas como
esta para perseguir esses erros.

1819
01:30:47,850 --> 01:30:50,460
>Caso contrário, coisas ruins podem acontecer.

1820
01:30:50,460 --> 01:30:51,600
>E o que pode acontecer?

1821
01:30:51,600 --> 01:30:54,900
>Bem, deixe-me ir em frente
e revelar um exemplo aqui
1822
01:30:54,900 --> 01:30:57,840
>que apresenta algum código
que é um pouco perigoso.

1823
01:30:57,840 --> 01:31:00,600
>Então aqui, por exemplo,
é um exemplo onde

1824
01:31:00,600 --> 01:31:05,202
>estou declarando no topo da
função, int asterisco x e int asterisco y.

1825
01:31:05,202 --> 01:31:06,160
>Então, o que isso significa?

1826
01:31:06,160 --> 01:31:08,700
>Bem, pela linguagem de hoje,
isso significa apenas me dê

1827
01:31:08,700 --> 01:31:11,550
>um ponteiro para um inteiro chamado x.

1828
01:31:11,550 --> 01:31:13,800
>Dê-me um ponteiro para
um inteiro chamado y.

1829
01:31:13,800 --> 01:31:16,650
>Dito de outra forma, dê-me uma
variável chamada x que eu

1830
01:31:16,650 --> 01:31:18,900
>possa armazenar o endereço de um int.

1831
01:31:18,900 --> 01:31:23,640
>Dê-me uma variável chamada y na qual
posso armazenar o endereço de outro int.

1832
01:31:23,640 --> 01:31:27,880
>Mas observe o que não estou fazendo
nessas duas primeiras linhas.

1833
01:31:27,880 --> 01:31:31,950
>Na verdade, não estou atribuindo
a elas um valor até a linha 3.

1834
01:31:31,950 --> 01:31:36,000
>Na linha 3, embora isso seja estranho -
não é assim que alocamos espaço

1835
01:31:36,000 --> 01:31:37,530
>para inteiros antes -

1836
01:31:37,530 --> 01:31:41,130
>não há razão para que você
não possa usar malloc

1837
01:31:41,130 --> 01:31:45,550
>e diga, dê-me espaço suficiente
para o tamanho de um inteiro.

1838
01:31:45,550 --> 01:31:46,370
>sizeof é novo.

1839
01:31:46,370 --> 01:31:50,150
>É apenas um operador em C que informa
o tamanho de um tipo de dados,

1840
01:31:50,150 --> 01:31:51,500
>como o tamanho de um int.

1841
01:31:51,500 --> 01:31:53,480
>Então, talvez você tenha esquecido que um int é 4.

1842
01:31:53,480 --> 01:31:56,450
>E, um int é geralmente 4,
mas nem sempre 4 em todos os sistemas.

1843
01:31:56,450 --> 01:32:00,020
>Portanto, o tamanho de int só garante
que sempre fornecerá a resposta certa,

1844
01:32:00,020 --> 01:32:02,630
>se você está usando um
computador moderno ou antigo.

1845
01:32:02,630 --> 01:32:07,190
>Então, isso significa, alocar
4 bytes para mim em um sistema moderno.

1846
01:32:07,190 --> 01:32:11,370
>E armazena o endereço
do primeiro byte em x.
1847
01:32:11,370 --> 01:32:15,360
>Alguém se importaria de traduzir
para termos leigos, o que

1848
01:32:15,360 --> 01:32:18,480
>asterisco x igual a 42 está fazendo?

1849
01:32:18,480 --> 01:32:20,880
>Asterisco, novamente, é o
operador de desreferência.

1850
01:32:20,880 --> 01:32:23,430
>Significa ir para o endereço.

1851
01:32:23,430 --> 01:32:24,375
>E fazer o que?

1852
01:32:24,375 --> 01:32:27,510
>Como você descreveria,
com um comentário verbal,

1853
01:32:27,510 --> 01:32:30,450
>o que asterisco x igual a 42 está fazendo?

1854
01:32:30,450 --> 01:32:33,630
>Brian, você se importaria de
verbalizar algum pensamento?

1855
01:32:33,630 --> 01:32:37,555
>BRIAN: Sim, então Sofia sugeriu que
nesse endereço, colocaremos o 42.

1856
01:32:37,555 --> 01:32:38,430
>DAVID MALAN: Perfeito.

1857
01:32:38,430 --> 01:32:40,080
>Nesse endereço, coloque 42.

1858
01:32:40,080 --> 01:32:44,640
>Equivalentemente, vá para aquele
endereço em x e coloque o número 42 lá.

1859
01:32:44,640 --> 01:32:48,870
>É como ir à caixa de correio de Brian e
colocar o 42 em sua caixa de correio,
1860
01:32:48,870 --> 01:32:52,035
>em vez do que tínhamos
anteriormente, que era o número 50.

1861
01:32:52,035 --> 01:32:57,180
>Que tal esta próxima quinta
linha, asterisco y é igual a 13?

1862
01:32:57,180 --> 01:32:59,670
>Brian, você poderia verbalizar outra pessoa?

1863
01:32:59,670 --> 01:33:03,500
>O que asterisco y igual a 13 faz por nós?

1864
01:33:03,500 --> 01:33:07,850
>E não é por acaso que
13 tende a ser azarado.

1865
01:33:07,850 --> 01:33:10,530
>BRIAN: Peter diz, coloque
13 no endereço y.

1866
01:33:10,530 --> 01:33:12,710
>DAVID MALAN: Bom, coloque
13 no endereço em y.

1867
01:33:12,710 --> 01:33:16,860
>Ou dito de outra forma, vá para o
endereço em y e coloque 13 lá.

1868
01:33:16,860 --> 01:33:19,070
>Mas há um problema lógico aqui.

1869
01:33:19,070 --> 01:33:20,870
>O que está em y?

1870
01:33:20,870 --> 01:33:24,860
>Se eu retroceder, nunca
atribuo um valor a y.

1871
01:33:24,860 --> 01:33:27,050
>Eu não faço inicialmente, e
eu não faço eventualmente.

1872
01:33:27,050 --> 01:33:30,500
>Pelo menos com x, embora eu não tenha
dado um valor ao declará-lo aqui

1873
01:33:30,500 --> 01:33:34,850
>como uma variável, acabei
armazenando nela o endereço real.

1874
01:33:34,850 --> 01:33:38,060
>Agora, apenas para ser minucioso,
eu provavelmente deveria, neste programa,

1875
01:33:38,060 --> 01:33:40,495
>verificar em nul
caso algo dê errado.

1876
01:33:40,495 --> 01:33:41,870
>Mas esse é um problema totalmente diferente.

1877
01:33:41,870 --> 01:33:46,470
>É um problema mais terrível que
eu sequer dei um valor a y.

1878
01:33:46,470 --> 01:33:49,610
>E é aqui que podemos revelar outro
detalhe sobre um computador.

1879
01:33:49,610 --> 01:33:53,750
>Até agora, consideramos que você
e eu quase sempre inicializamos

1880
01:33:53,750 --> 01:33:54,360
>nossa memória.

1881
01:33:54,360 --> 01:33:56,900
>Se quisermos nos dar um
char, um int, uma string,

1882
01:33:56,900 --> 01:33:59,900
>nós literalmente
digitamos no programa

1883
01:33:59,900 --> 01:34:02,150
>para que esteja
lá quando quisermos.

1884
01:34:02,150 --> 01:34:04,070
>Mas se considerarmos
esta imagem aqui, que
1885
01:34:04,070 --> 01:34:07,370
>agora é uma encarnação física de
alguns dos conteúdos da memória

1886
01:34:07,370 --> 01:34:11,750
>do seu computador, divertidamente rotulada
com muito Oscars,

1887
01:34:11,750 --> 01:34:16,250
>isso é porque você nunca deve confiar no
conteúdo da memória do seu computador

1888
01:34:16,250 --> 01:34:18,500
>se você mesmo não
colocou algo lá.

1889
01:34:18,500 --> 01:34:21,560
>Existe um termo técnico em
programação chamado valores de lixo.

1890
01:34:21,560 --> 01:34:26,180
>Se você mesmo não colocou um
valor em algum lugar da memória,

1891
01:34:26,180 --> 01:34:30,210
>você deve assumir, para estar seguro, que
é "valor de lixo".

1892
01:34:30,210 --> 01:34:31,440
>Não é um valor estranho.

1893
01:34:31,440 --> 01:34:34,580
>É apenas 1, 2, um A, a B, o C, você apenas

1894
01:34:34,580 --> 01:34:38,510
>não sabe o que é, porque se o seu
programa está rodando

1895
01:34:38,510 --> 01:34:40,890
>e você está chamando funções
e funções estão retornando.

1896
01:34:40,890 --> 01:34:43,348
>Você está chamando outras funções
e as funções estão retornando.
1897
01:34:43,348 --> 01:34:46,970
>Esses valores na memória do seu
computador estão mudando constantemente,

1898
01:34:46,970 --> 01:34:48,740
>e sua memória é reutilizada.

1899
01:34:48,740 --> 01:34:53,180
>Quando você libera memória, isso não a apaga
ou define tudo de volta para zero ou define

1900
01:34:53,180 --> 01:34:53,990
>tudo de volta para 1's.

1901
01:34:53,990 --> 01:34:56,600
>Ele apenas deixa estar
para que você possa reutilizar

1902
01:34:56,600 --> 01:34:59,810
>isso, o que significa com o tempo,
seu computador contém resquícios

1903
01:34:59,810 --> 01:35:03,960
>de todas as variáveis que você já
usou em seu programa aqui, aqui,

1904
01:35:03,960 --> 01:35:04,730
>e lá.

1905
01:35:04,730 --> 01:35:10,850
>E dessa forma, em um programa assim, onde
você não inicializou explicitamente y

1906
01:35:10,850 --> 01:35:14,000
>a qualquer coisa, você deve presumir
que Oscar, por assim dizer,

1907
01:35:14,000 --> 01:35:15,020
>está nesse local.

1908
01:35:15,020 --> 01:35:20,570
>É um valor lixo que se parece com um
endereço, mas não é um endereço válido.

1909
01:35:20,570 --> 01:35:25,040
>E então, quando você diz asterisco y é igual a
13, isso significa ir para esse endereço.

1910
01:35:25,040 --> 01:35:28,910
>Mas, vá para aquele
endereço falso e coloque algo lá.

1911
01:35:28,910 --> 01:35:31,850
>E as chances são de que
seu programa irá falhar.

1912
01:35:31,850 --> 01:35:33,650
>Você vai ter uma falha
de segmentação,

1913
01:35:33,650 --> 01:35:37,562
>porque indo para algum endereço
de valor de lixo arbitrário,

1914
01:35:37,562 --> 01:35:40,520
>seria como pegar um pedaço de
papel aleatório com um número

1915
01:35:40,520 --> 01:35:42,030
>e então indo para essa caixa de correio.

1916
01:35:42,030 --> 01:35:42,530
>Por quê?

1917
01:35:42,530 --> 01:35:44,300
>Isso pertence a você.

1918
01:35:44,300 --> 01:35:47,930
>Se você tentar cancelar a referência
de uma variável não inicializada,

1919
01:35:47,930 --> 01:35:49,850
>seu programa pode muito bem travar.

1920
01:35:49,850 --> 01:35:51,890
>E isso é, talvez,
não melhor apresentado

1921
01:35:51,890 --> 01:35:55,970
>do que por alguns de nossos amigos, Nick
Parlante, um professor em Stanford

1922
01:35:55,970 --> 01:36:02,510
>Universidade que dá vida a um caractere
em claymation conhecido como Binky.

1923
01:36:02,510 --> 01:36:06,140
>Temos um clipe de 2 minutos disso
que mostra o quadro das coisas ruins

1924
01:36:06,140 --> 01:36:09,020
>acontecendo quando você
toca a memória que você não deveria.

1925
01:36:09,020 --> 01:36:13,340
>Felizmente, um lembrete útil sobre o que
fazer e o que não fazer com os ponteiros.

1926
01:36:13,340 --> 01:36:14,790
>Aqui vamos nós.

1927
01:36:14,790 --> 01:36:16,610
>[REPRODUÇÃO DE VÍDEO]

1928
01:36:16,610 --> 01:36:17,540
>- Ei, Binky.

1929
01:36:17,540 --> 01:36:20,890
>Acorde, é hora de se divertir com o ponteiro.

1930
01:36:20,890 --> 01:36:22,060
>- O que é aquilo?

1931
01:36:22,060 --> 01:36:23,620
>Aprender sobre ponteiros?

1932
01:36:23,620 --> 01:36:25,390
>Oh, que bom!

1933
01:36:25,390 --> 01:36:28,430
>- Bem, para começar, acho que
vamos precisar de algumas dicas.

1934
01:36:28,430 --> 01:36:32,940
>- OK, este código aloca dois ponteiros
que podem apontar para inteiros.

1935
01:36:32,940 --> 01:36:35,042
>- OK, bem, vejo as duas dicas.

1936
01:36:35,042 --> 01:36:37,000
>Mas eles não parecem estar
apontando para nada.

1937
01:36:37,000 --> 01:36:37,780
>- Isso está certo.

1938
01:36:37,780 --> 01:36:39,970
>Inicialmente, os ponteiros
não apontam para nada.

1939
01:36:39,970 --> 01:36:42,190
>As coisas para as quais eles
apontam são chamadas de pontas.

1940
01:36:42,190 --> 01:36:44,110
>E configurá-las é uma etapa separada.

1941
01:36:44,110 --> 01:36:45,100
>- Oh, certo, certo.

1942
01:36:45,100 --> 01:36:45,790
>Eu sabia.

1943
01:36:45,790 --> 01:36:47,750
>As pontas são separadas.

1944
01:36:47,750 --> 01:36:50,050
>Então, como você aloca uma ponta?

1945
01:36:50,050 --> 01:36:53,800
>- OK, bem, este código aloca
uma nova ponta inteira.

1946
01:36:53,800 --> 01:36:56,880
>E esta parte define x para apontar para ele.

1947
01:36:56,880 --> 01:36:58,180
>- Ei, isso parece melhor.

1948
01:36:58,180 --> 01:36:59,700
>Então faça algo.

1949
01:36:59,700 --> 01:37:05,460
>- OK, vou desreferenciar o ponteiro x
para armazenar o número 42 em sua ponta.

1950
01:37:05,460 --> 01:37:08,970
>Para este truque, vou precisar da minha
varinha mágica de desreferenciação.

1951
01:37:08,970 --> 01:37:12,660
>- Sua varinha mágica de desreferenciação?

1952
01:37:12,660 --> 01:37:14,170
>Isso é ótimo.

1953
01:37:14,170 --> 01:37:15,910
>- É assim que o código se parece.

1954
01:37:15,910 --> 01:37:17,800
>Vou apenas configurar o número e -

1955
01:37:18,900 --> 01:37:21,000
>- Ei, olha, aí vai.

1956
01:37:21,000 --> 01:37:25,830
>Portanto, fazer uma desreferenciação em
x segue a seta para acessar sua ponta.

1957
01:37:25,830 --> 01:37:28,020
>Nesse caso, para armazenar 42 ali.

1958
01:37:28,020 --> 01:37:32,450
>Ei, tente usá-lo para armazenar o número
13 por meio do outro ponteiro, y.

1959
01:37:32,450 --> 01:37:33,570
>- OK.

1960
01:37:33,570 --> 01:37:38,100
>Vou apenas ir aqui para y e
obter o número 13 configurado

1961
01:37:38,100 --> 01:37:41,970
>e, em seguida, pegar a varinha
de desreferenciação e apenas -

1962
01:37:41,970 --> 01:37:43,580
> uau!

1963
01:37:43,580 --> 01:37:45,930
>- Oh, ei, isso não funcionou.

1964
01:37:45,930 --> 01:37:51,370
>Diga, Binky, não acho que desreferenciar
y seja uma boa ideia, porque configurar

1965
01:37:51,370 --> 01:37:52,840
>a ponta é uma etapa separada.

1966
01:37:52,840 --> 01:37:54,815
>E acho que nunca fizemos isso.

1967
01:37:54,815 --> 01:37:56,430
>- Hmm, bom ponto.

1968
01:37:56,430 --> 01:37:58,800
>- Sim, alocamos o ponteiro y.

1969
01:37:58,800 --> 01:38:01,570
>Mas nunca o definimos para
apontar para uma ponta.

1970
01:38:01,570 --> 01:38:03,480
>- Hmm, muito observador.

1971
01:38:03,480 --> 01:38:05,310
>- Ei, você está bem aí, Binky.

1972
01:38:05,310 --> 01:38:08,250
>Você pode corrigi-lo de forma que
y aponte para a mesma ponta de x?

1973
01:38:08,250 --> 01:38:11,620
>- Claro, vou usar minha varinha
mágica de atribuição de ponteiro.

1974
01:38:11,620 --> 01:38:13,800
>- Isso vai ser um
problema como antes?

1975
01:38:13,800 --> 01:38:15,630
>- Não, isso não toca nas pontas.
1976
01:38:15,630 --> 01:38:19,170
>Ele apenas muda um ponteiro para
apontar para a mesma coisa que outro.

1977
01:38:19,170 --> 01:38:20,310
>- Oh, entendi.

1978
01:38:20,310 --> 01:38:23,040
>Agora, y aponta para o mesmo lugar que x.

1979
01:38:23,040 --> 01:38:24,840
>Então espere, agora y está consertado.

1980
01:38:24,840 --> 01:38:25,950
>Tem uma ponta.

1981
01:38:25,950 --> 01:38:29,760
>Portanto, você pode tentar a varinha de
desreferenciação novamente para enviar o 13.

1982
01:38:29,760 --> 01:38:31,093
>- Ah ok.

1983
01:38:31,093 --> 01:38:31,635
>Aqui vai.

1984
01:38:32,900 --> 01:38:34,160
>- Ei, olha isso.

1985
01:38:34,160 --> 01:38:35,870
>Agora, o desreferenciação funciona em y.

1986
01:38:35,870 --> 01:38:39,980
>porque os ponteiros estão compartilhando
aquele ponto, ambos veem o 13.

1987
01:38:39,980 --> 01:38:41,720
>- Sim, compartilhando, tanto faz.

1988
01:38:41,720 --> 01:38:43,610
>Então, vamos trocar de lugar agora?

1989
01:38:43,610 --> 01:38:45,270
>- Oh, olhe, estamos sem tempo.
1990
01:38:45,270 --> 01:38:45,770
>- Mas--

1991
01:38:45,770 --> 01:38:46,040
>[FIM DA REPRODUÇÃO]

1992
01:38:46,040 --> 01:38:47,570
>DAVID MALAN: Tudo bem, então
não estamos muito sem tempo.

1993
01:38:47,570 --> 01:38:50,028
>Mas vamos prosseguir e fazer nosso
segundo intervalo de 5 minutos aqui.

1994
01:38:50,028 --> 01:38:52,910
>E quando voltarmos, daremos uma olhada
mais de perto do Oscar e muito mais.

1995
01:38:52,910 --> 01:38:54,260
>De volta em 5.

1996
01:38:54,260 --> 01:38:57,380
>Tudo bem, então eu afirmo
que há todo esse lixo

1997
01:38:57,380 --> 01:38:58,950
>de valores na memória do seu computador.

1998
01:38:58,950 --> 01:39:00,860
>Mas como você pode vê-los?

1999
01:39:00,860 --> 01:39:04,400
>O que Binky fez foi, claro,
tentar cancelar a deferência de um valor de lixo

2000
01:39:04,400 --> 01:39:05,817
>quando coisas ruins acontecem.

2001
01:39:05,817 --> 01:39:07,900
>Mas podemos ver isso
com nosso próprio código.

2002
01:39:07,900 --> 01:39:10,970
>Então, agora eu vou
preparar um pequeno programa aqui,
2003
01:39:10,970 --> 01:39:15,290
>como algo que fizemos na
primeira ou segunda semana,

2004
01:39:15,290 --> 01:39:17,090
>mas sem fazer muito bem.

2005
01:39:17,090 --> 01:39:21,410
>Eu vou incluir o padrão io
ponto h, como de costume, int main void.

2006
01:39:21,410 --> 01:39:24,290
>E então agora eu vou dar a
mim mesmo uma série de scores.

2007
01:39:24,290 --> 01:39:26,000
>Que tal uma série de três scores?

2008
01:39:26,000 --> 01:39:28,715
>E já fizemos isso antes, quando
coletamos as scores de um usuário.

2009
01:39:28,715 --> 01:39:30,590
>Mas desta vez, vou
fazer deliberadamente

2010
01:39:30,590 --> 01:39:33,170
>o erro de não inicializar
essas scores

2011
01:39:33,170 --> 01:39:35,450
>ou mesmo pedindo ao humano
por essas scores.

2012
01:39:35,450 --> 01:39:41,060
>Vou continuar repetindo
cegamente de i igual a 0 até 3.

2013
01:39:41,060 --> 01:39:46,070
>E em cada iteração, vou imprimir
presunçosamente o que quer que seja

2014
01:39:46,070 --> 01:39:49,220
>naquele local na faixa de score i.

2015
01:39:49,220 --> 01:39:52,430
>Então, logicamente, meu código está
correto no que está tentando fazer,

2016
01:39:52,430 --> 01:39:54,230
>imprimir os valores em scores.

2017
01:39:54,230 --> 01:39:57,170
>Mas note que eu deliberadamente
não inicializei nenhuma

2018
01:39:57,170 --> 01:40:00,147
>das scores 1, 2, 3 nesse array.

2019
01:40:00,147 --> 01:40:01,730
>Então, quem sabe o que vai estar lá?

2020
01:40:01,730 --> 01:40:04,650
>Na verdade, devem ser valores
de lixo de algum tipo

2021
01:40:04,650 --> 01:40:06,650
>que não poderíamos necessariamente
prever antes.

2022
01:40:06,650 --> 01:40:10,050
>Então, agora eu vou fazer
lixo, uma vez que este programa

2023
01:40:10,050 --> 01:40:11,300
>está em um arquivo chamado garbage.c.

2024
01:40:11,300 --> 01:40:15,140
>Compila OK, mas quando
eu agora rodo garbage, nós

2025
01:40:15,140 --> 01:40:21,230
>devemos ver três scores, que são
cripticamente negativas, 833060864.

2026
01:40:21,230 --> 01:40:23,780
>Outro é 32765.

2027
01:40:23,780 --> 01:40:25,760
>E o terceiro simplesmente é 0.

2028
01:40:25,760 --> 01:40:28,490
>Então, existem esses valores de lixo,
porque novamente, o computador

2029
01:40:28,490 --> 01:40:31,800
>não inicializará nenhum
desses valores para você.

2030
01:40:31,800 --> 01:40:33,570
>Agora, existem exceções.

2031
01:40:33,570 --> 01:40:36,320
>Temos, na ocasião,
usou uma variável global,

2032
01:40:36,320 --> 01:40:40,490
>uma constante que está fora do contexto de
principal e de todas as minhas outras funções.

2033
01:40:40,490 --> 01:40:42,860
>Variáveis globais, se
você não defini-las,

2034
01:40:42,860 --> 01:40:47,210
>são inicializados convencionalmente
como 0 ou nul para você.

2035
01:40:47,210 --> 01:40:50,000
>Mas você geralmente não deve confiar
nesse tipo de comportamento.

2036
01:40:50,000 --> 01:40:53,120
>Seu instinto deve ser
sempre inicializar valores

2037
01:40:53,120 --> 01:40:56,630
>antes de pensar em
tocá-los ou lê-los

2038
01:40:56,630 --> 01:40:59,030
>como via printf ou algum outro mecanismo.

2039
01:40:59,030 --> 01:41:02,720
>Tudo bem, vamos ver como esse
entendimento, agora, de memória,

2040
01:41:02,720 --> 01:41:06,350
>pode nos levar a resolver problemas, mas
também encontrar novos tipos de problemas,

2041
01:41:06,350 --> 01:41:08,960
>mas problemas que agora
podemos entender.

2042
01:41:08,960 --> 01:41:11,250
>Vou prosseguir e criar
um novo programa aqui.

2043
01:41:11,250 --> 01:41:14,390
>E lembre-se da semana
passada que era muito comum

2044
01:41:14,390 --> 01:41:15,890
>querermos trocar valores.

2045
01:41:15,890 --> 01:41:19,010
>Quando Brian estava fazendo nossa
classificação por nós, fosse seleção ou bubble sort

2046
01:41:19,010 --> 01:41:21,710
>havia muitas
trocas acontecendo.

2047
01:41:21,710 --> 01:41:24,440
>Mesmo assim, não escrevemos nenhum
código para esses algoritmos.

2048
01:41:24,440 --> 01:41:25,232
>E isso é bom.

2049
01:41:25,232 --> 01:41:27,440
>Mas vamos considerar aquele
primitivo muito simples de apenas

2050
01:41:27,440 --> 01:41:30,440
>trocar dois valores, por
exemplo, trocando dois inteiros.

2051
01:41:30,440 --> 01:41:34,160
>Vamos prosseguir e iniciar
um programa e swap.c aqui.

2052
01:41:34,160 --> 01:41:38,630
>Vou incluir o padrão io
ponto h, int main void.
2053
01:41:38,630 --> 01:41:41,370
>E dentro do principal, vou
me dar dois inteiros.

2054
01:41:41,370 --> 01:41:44,960
>Vou criar um int chamado x
e atribuir a ele 1, um int chamado y

2055
01:41:44,960 --> 01:41:46,140
>e atribuir 2.

2056
01:41:46,140 --> 01:41:48,890
>E então agora eu vou
imprimir quais são esses valores.

2057
01:41:48,890 --> 01:41:55,520
>Direi apenas, x é percentual i
vírgula y é percentual i \ n.

2058
01:41:55,520 --> 01:41:59,490
>E então prosseguirei e imprimirei
x vírgula y, respectivamente.

2059
01:41:59,490 --> 01:42:02,930
>E então, eventualmente, irei
escrever uma função chamada

2060
01:42:02,930 --> 01:42:04,613
>swap que troca x e y.

2061
01:42:04,613 --> 01:42:06,530
>Mas vamos supor, por
enquanto, que exista.

2062
01:42:06,530 --> 01:42:08,870
>Não existe, porque o que
então eu quero fazer o certo

2063
01:42:08,870 --> 01:42:13,340
>depois disso, é reimprimir a
mesma coisa, x agora é % i,

2064
01:42:13,340 --> 01:42:17,690
>y é % i, minha suposição
é que os valores de x e y
2065
01:42:17,690 --> 01:42:18,870
>serão trocados.

2066
01:42:18,870 --> 01:42:20,480
>Então, como posso trocar esses dois valores?

2067
01:42:20,480 --> 01:42:23,120
>Bem, deixe-me seguir em frente e
implementar minha própria função.

2068
01:42:23,120 --> 01:42:25,110
>Não acho que precise
retornar nada,

2069
01:42:25,110 --> 01:42:27,110
>então direi void é
o tipo de retorno.

2070
01:42:27,110 --> 01:42:28,340
>Vou chamar de swap.

2071
01:42:28,340 --> 01:42:30,830
>Terá dois argumentos
como entrada.

2072
01:42:30,830 --> 01:42:33,320
>Vamos chamar de a e b, ambos inteiros.

2073
01:42:33,320 --> 01:42:34,820
>Mas eu poderia chamar do que eu quiser.

2074
01:42:34,820 --> 01:42:36,800
>Mas a e b parecem razoáveis.

2075
01:42:36,800 --> 01:42:39,350
>E agora, quero ir em frente
e trocar dois valores.

2076
01:42:39,350 --> 01:42:42,140
>Agora, Brian estava fazendo isso com
as duas mãos na semana passada.

2077
01:42:42,140 --> 01:42:45,830
>E isso é bom, mas provavelmente devemos
considerar isso um pouco mais de perto.
2078
01:42:45,830 --> 01:42:48,050
>Na verdade, Brian, em
vez de números, vamos

2079
01:42:48,050 --> 01:42:49,920
>faça algo um pouco mais do mundo real.

2080
01:42:49,920 --> 01:42:53,080
>Acho que você tem algumas
bebidas na sua frente.

2081
01:42:53,080 --> 01:42:53,580
>BRIAN: Sim.

2082
01:42:53,580 --> 01:42:56,220
>Então, bem aqui, eu tenho um
vidro vermelho e um vidro azul,

2083
01:42:56,220 --> 01:42:58,970
>que acho que podemos usar para
representar duas variáveis, por exemplo.

2084
01:42:58,970 --> 01:42:59,180
>DAVID MALAN: Sim.

2085
01:42:59,180 --> 01:43:00,198
>Agora, deixe-me supor -

2086
01:43:00,198 --> 01:43:01,490
>Eu gostaria de ter contado a você antes.

2087
01:43:01,490 --> 01:43:03,920
>Na verdade, prefiro que
o líquido vermelho seja

2088
01:43:03,920 --> 01:43:07,050
>no vidro azul e o líquido
azul no vidro vermelho.

2089
01:43:07,050 --> 01:43:08,780
>Então você se importa em
trocar esses dois valores,

2090
01:43:08,780 --> 01:43:11,310
>assim como você trocou de números na semana passada?
2091
01:43:11,310 --> 01:43:12,060
>BRIAN: Sim, claro.

2092
01:43:12,060 --> 01:43:14,810
>Então, posso apenas pegar os dois copos,
e posso trocar de lugar.

2093
01:43:14,810 --> 01:43:17,717
>DAVID MALAN: OK, espere,
OK, isso não é exatamente -

2094
01:43:17,717 --> 01:43:18,800
>você me interpretou muito literalmente.

2095
01:43:18,800 --> 01:43:22,760
>Acho que aqui, se pensarmos no copos,
agora, como locais específicos

2096
01:43:22,760 --> 01:43:24,980
>na memória, você não pode
apenas mover fisicamente

2097
01:43:24,980 --> 01:43:27,540
>os chips de memória dentro do seu
computador para trocar coisas.

2098
01:43:27,540 --> 01:43:30,410
>Acho que literalmente preciso
que você mova o líquido azul

2099
01:43:30,410 --> 01:43:33,350
>no vidro vermelho e o líquido
vermelho no vidro azul

2100
01:43:33,350 --> 01:43:36,100
>para que seja mais como a
memória de um computador.

2101
01:43:36,100 --> 01:43:37,657
>BRIAN: OK, posso tentar fazer isso.

2102
01:43:37,657 --> 01:43:40,240
>Estou um pouco nervoso, no entanto,
porque eu sinto que não posso simplesmente

2103
01:43:40,240 --> 01:43:43,270
>despejar o líquido azul no vidro vermelho,
porque o líquido vermelho já está

2104
01:43:43,270 --> 01:43:43,640
>lá.

2105
01:43:43,640 --> 01:43:45,730
>DAVID MALAN: Sim, então isso
provavelmente não termina bem,

2106
01:43:45,730 --> 01:43:48,220
>se ele tem que fazer algum tipo
de troca entre os dois copos.

2107
01:43:48,220 --> 01:43:49,240
>Então, alguma ideia aqui?

2108
01:43:49,240 --> 01:43:54,100
>Como qual é a solução do mundo real para
este problema estranho, mas real, onde

2109
01:43:54,100 --> 01:43:57,490
>queremos trocar o conteúdo
desses dois locais,

2110
01:43:57,490 --> 01:44:01,180
>assim como Brian estava trocando o
conteúdo de dois locais de memória

2111
01:44:01,180 --> 01:44:02,290
>na semana anterior?

2112
01:44:02,290 --> 01:44:04,900
>Brian, se você estiver de
olho no chat em paralelo,

2113
01:44:04,900 --> 01:44:08,480
>alguém poderia ter ideias sobre como
poderíamos trocar esses dois líquidos?

2114
01:44:08,480 --> 01:44:11,620
>BRIAN: Sim, algumas pessoas estão dizendo
que preciso de um terceiro copo.

2115
01:44:11,620 --> 01:44:13,370
>DAVID MALAN: Tudo bem,
bem Brian, você
2116
01:44:13,370 --> 01:44:16,370
>por acaso tem um terceiro
copo com você atrás do palco?

2117
01:44:16,370 --> 01:44:18,040
>BRIAN: Na verdade, acho que sim.

2118
01:44:18,040 --> 01:44:21,190
>Então, eu tenho um terceiro copo
aqui que por acaso está vazio.

2119
01:44:21,190 --> 01:44:22,100
>DAVID MALAN: OK.

2120
01:44:22,100 --> 01:44:25,610
>E como você faria para
trocar essas duas coisas?

2121
01:44:25,610 --> 01:44:28,870
>BRIAN: Tudo bem, então eu quero colocar
o líquido azul dentro do copo vermelho.

2122
01:44:28,870 --> 01:44:30,578
>Então, a primeira coisa que
preciso fazer, eu acho,

2123
01:44:30,578 --> 01:44:34,040
>é esvaziar o copo vermelho
para dar espaço ao líquido azul.

2124
01:44:34,040 --> 01:44:36,310
>Vou pegar o líquido
vermelho e só

2125
01:44:36,310 --> 01:44:38,470
>vou despejá-lo neste copo extra.

2126
01:44:38,470 --> 01:44:39,520
>DAVID MALAN: Mas temporariamente, certo?

2127
01:44:39,520 --> 01:44:39,870
>BRIAN: Temporariamente, sim.

2128
01:44:39,870 --> 01:44:40,570
>DAVID MALAN: OK.
2129
01:44:40,570 --> 01:44:42,620
>BRIAN: Só para guardar aí.

2130
01:44:42,620 --> 01:44:45,100
>E agora, acho que posso apenas
derramar o líquido azul

2131
01:44:45,100 --> 01:44:48,942
>no vidro vermelho original,
porque agora estou livre para fazer isso.

2132
01:44:48,942 --> 01:44:50,400
>Então, vou derramar o líquido azul ali.

2133
01:44:53,230 --> 01:44:56,220
>E acho que a última coisa que preciso
fazer agora é, agora este azul -

2134
01:44:56,220 --> 01:44:59,680
>este copo que originalmente continha
o líquido azul agora está vazio.

2135
01:44:59,680 --> 01:45:03,130
>Então, o líquido vermelho, que estava
dentro deste vidro temporário aqui,

2136
01:45:03,130 --> 01:45:07,350
>Posso pegar o líquido vermelho e
apenas despejá-lo neste copo aqui.

2137
01:45:07,350 --> 01:45:10,290
>E agora, não troquei as
posições dos copos.

2138
01:45:10,290 --> 01:45:12,390
>Mas os líquidos
trocaram de lugar.

2139
01:45:12,390 --> 01:45:15,355
>Agora, o líquido azul está à esquerda
e o líquido vermelho está à direita.

2140
01:45:15,355 --> 01:45:16,230
>DAVID MALAN: Incrível.

2141
01:45:16,230 --> 01:45:18,660
>Sim, acho que é uma
implementação mais literal

2142
01:45:18,660 --> 01:45:21,150
>do que você estava fazendo e dando
como certo na semana passada,

2143
01:45:21,150 --> 01:45:24,182
>trocando os dois valores
em dois locais separados.

2144
01:45:24,182 --> 01:45:25,640
>Portanto, parece muito simples.

2145
01:45:25,640 --> 01:45:27,210
>Só preciso de um pouco mais de espaço.

2146
01:45:27,210 --> 01:45:29,670
>Preciso de uma variável
temporária no código.

2147
01:45:29,670 --> 01:45:31,545
>E parece que preciso de três etapas.

2148
01:45:31,545 --> 01:45:34,670
>Eu preciso derramar um, despejar o
outro fora, despejar o outro de volta.

2149
01:45:34,670 --> 01:45:37,122
>Então, acho que posso
traduzir isso em código aqui.

2150
01:45:37,122 --> 01:45:39,330
>Eu vou me
dar uma variável temporária,

2151
01:45:39,330 --> 01:45:40,840
>como um copo, como Brian fez.

2152
01:45:40,840 --> 01:45:43,650
>E vou chamar de tmp, T-M-P,
o que é bem convencional quando

2153
01:45:43,650 --> 01:45:45,180
>é melhor trocar duas coisas no código.
2154
01:45:45,180 --> 01:45:47,850
>E eu vou assinar,
temporariamente, o valor de a.

2155
01:45:47,850 --> 01:45:51,550
>Vou então alterar o conteúdo de a para
igual a qualquer que seja o conteúdo de B

2156
01:45:52,050 --> 01:45:56,010
>E então vou mudar b para ser qualquer
que fosse o conteúdo de tmp.

2157
01:45:56,010 --> 01:45:58,650
>Isso parece bastante
razoável e correto,

2158
01:45:58,650 --> 01:46:01,230
>porque é uma
tradução literal em código,

2159
01:46:01,230 --> 01:46:03,700
>agora, do que Brian
fez no mundo real.

2160
01:46:03,700 --> 01:46:05,610
>E acho que isso vai compilar.

2161
01:46:05,610 --> 01:46:08,040
>Então, vamos começar por aí, fazer a troca.

2162
01:46:08,040 --> 01:46:09,690
>Ele -- não compila.

2163
01:46:09,690 --> 01:46:13,410
>OK, declaração implícita anterior,
tantos erros, meu Deus.

2164
01:46:13,410 --> 01:46:15,687
>Declaração implícita de troca de função -

2165
01:46:15,687 --> 01:46:16,270
>espere um minuto.

2166
01:46:16,270 --> 01:46:17,230
>Eu já vi isso antes.
2167
01:46:17,230 --> 01:46:18,480
>Já cometi esse erro antes.

2168
01:46:18,480 --> 01:46:20,050
>Você também pode ter cometido.

2169
01:46:20,050 --> 01:46:23,293
>Sempre que vir isso, lembre-se de
que está faltando seu protótipo.

2170
01:46:23,293 --> 01:46:25,710
>Lembre-se de que o compilador
irá interpretá-lo literalmente.

2171
01:46:25,710 --> 01:46:28,500
>E se ele não souber que a palavra
troca existe quando a vir,

2172
01:46:28,500 --> 01:46:30,310
>não vai ser compilado com sucesso.

2173
01:46:30,310 --> 01:46:33,030
>Portanto, precisamos incluir meu
protótipo no topo do meu arquivo.

2174
01:46:33,030 --> 01:46:35,460
>Agora, deixe-me tentar novamente, make swap.

2175
01:46:35,460 --> 01:46:36,780
>OK, isso compila.

2176
01:46:36,780 --> 01:46:40,950
>Vou continuar agora e executar o
swap e relembrar que, em geral, o que eu fiz

2177
01:46:40,950 --> 01:46:43,380
>foi inicializado x para 1, y para 2.

2178
01:46:43,380 --> 01:46:45,900
>Em seguida, imprimo o
que é x e o que é y.

2179
01:46:45,900 --> 01:46:50,040
>Eu chamo swap e imprimo
o que é x e y novamente.
2180
01:46:50,040 --> 01:46:52,770
>Devo ver 1, 2 e 2, 1.

2181
01:46:52,770 --> 01:46:55,430
>Então, vamos apertar Enter.

2182
01:46:55,430 --> 01:46:58,800
>Huh, não parece estar funcionando.

2183
01:46:58,800 --> 01:47:01,740
>Bem, vamos tentar novamente, apenas no caso -

2184
01:47:01,740 --> 01:47:04,020
>não, não está funcionando.

2185
01:47:04,020 --> 01:47:05,530
>Bem, deixe-me tentar isso.

2186
01:47:05,530 --> 01:47:07,590
>Vamos adicionar alguns-- printf é meu amigo.

2187
01:47:07,590 --> 01:47:10,971
>Vamos prosseguir e dizer que a é % i.

2188
01:47:10,971 --> 01:47:14,460
>b é a % i \ n, a, b.

2189
01:47:14,460 --> 01:47:15,510
>Então, vamos imprimir isso.

2190
01:47:15,510 --> 01:47:16,650
>E vamos imprimir isso duas vezes.

2191
01:47:16,650 --> 01:47:18,480
>Portanto, esta seria uma
técnica de depuração razoável.

2192
01:47:18,480 --> 01:47:21,605
>Se você quiser saber o que está acontecendo
por baixo do capô, adicione alguns printf's.

2193
01:47:21,605 --> 01:47:23,760
>Eu vou fazer make swap.

2194
01:47:23,760 --> 01:47:26,520
>Isso compila, ./swap.

2195
01:47:26,520 --> 01:47:32,880
>E vamos ver, a é 1,
b é 2, a é 2, b é 1.

2196
01:47:32,880 --> 01:47:35,470
>Mas então x e y permanecem inalterados.

2197
01:47:35,470 --> 01:47:37,170
>Então eu sinto que minha lógica está certa.

2198
01:47:37,170 --> 01:47:38,550
>Está trocando a e b.

2199
01:47:38,550 --> 01:47:41,490
>Mas, na verdade, não está trocando x e y.

2200
01:47:41,490 --> 01:47:43,340
>E eu poderia confirmar isso, certo?

2201
01:47:43,340 --> 01:47:45,510
>A maneira mais poderosa
de depurar isso seria

2202
01:47:45,510 --> 01:47:49,890
>executar debug50, definir um ponto
de interrupção, por exemplo, na linha 17,

2203
01:47:49,890 --> 01:47:54,270
>percorrer meu código, passo a passo,
entrando na função swap.

2204
01:47:54,270 --> 01:47:57,030
>Mas, por enquanto, parece
claro que a troca funciona.

2205
01:47:57,030 --> 01:48:00,250
>Mas o main não está
vendo esses resultados.

2206
01:48:00,250 --> 01:48:01,450
>Então, o que está acontecendo?

2207
01:48:01,450 --> 01:48:04,170
>Bem, vamos considerar esta encarnação
do mundo real do que minha memória é

2208
01:48:04,170 --> 01:48:05,712
>para que eu possa mover as coisas.

2209
01:48:05,712 --> 01:48:08,820
>E tudo isso graças aos nossos amigos na
loja de acessórios do teatro nos fundos.

2210
01:48:08,820 --> 01:48:10,830
>Se pensarmos nisso como a
memória do meu computador,

2211
01:48:10,830 --> 01:48:12,540
>inicialmente, são todos valores de lixo.

2212
01:48:12,540 --> 01:48:16,080
>Mas posso usar isso como uma tela para
começar a projetar as coisas na memória.

2213
01:48:16,080 --> 01:48:19,020
>Mas chamar funções é algo que
achamos ser algo fácil e tranquilo, até aqui.

2214
01:48:19,020 --> 01:48:22,200
>E acontece que, quando você chama
funções, o computador, por padrão,

2215
01:48:22,200 --> 01:48:25,500
>usa essa memória de
uma forma padrão.

2216
01:48:25,500 --> 01:48:29,850
>Na verdade, agora eu vou
fazer um desenho mais gráfico.

2217
01:48:29,850 --> 01:48:33,440
>Vamos desenhar uma imagem mais literal aqui,
se assim preferir, da memória do computador

2218
01:48:33,440 --> 01:48:33,940
>novamente.

2219
01:48:33,940 --> 01:48:36,660
>Então, se esta for a memória do computador
e fizermos zoom em um dos chips,
2220
01:48:36,660 --> 01:48:39,120
>e pensamos no chip como tendo
um monte de bytes assim.

2221
01:48:39,120 --> 01:48:42,390
>Vamos abstrair o hardware real
e pensar nele como sempre foi.

2222
01:48:42,390 --> 01:48:45,720
>É apenas esta grande região retangular da
memória, não muito diferente de todos aqueles

2223
01:48:45,720 --> 01:48:47,520
>Oscars de um momento atrás.

2224
01:48:47,520 --> 01:48:51,150
>Mas, por convenção, seu computador
não fica apenas inserindo coisas

2225
01:48:51,150 --> 01:48:52,710
>em locais aleatórios na memória.

2226
01:48:52,710 --> 01:48:55,710
>Ele segue certas
regras básicas.

2227
01:48:55,710 --> 01:48:59,460
>Em particular, ele trata diferentes
partes da memória do seu computador

2228
01:48:59,460 --> 01:49:00,330
>de maneiras diferentes.

2229
01:49:00,330 --> 01:49:03,570
>Ele o usa de uma maneira padrão para
que não seja completamente aleatório.

2230
01:49:03,570 --> 01:49:08,910
>Por exemplo, quando você executa um programa
fazendo alguma ./ no IDE CS50

2231
01:49:08,910 --> 01:49:12,270
>ou no Linux de forma mais geral, ou você
clica duas vezes em um ícone no Mac OS

2232
01:49:12,270 --> 01:49:16,590
>ou Windows, que
aciona o computador -

2233
01:49:16,590 --> 01:49:21,030
>os 0's e 1's do programa armazenados no seu
disco rígido para serem carregados aqui,

2234
01:49:21,030 --> 01:49:23,742
>ao que chamaremos de código de máquina,
que, novamente, são os 0's e 1's.

2235
01:49:23,742 --> 01:49:25,950
>Então, se você pensar novamente,
metaforicamente, como sua memória

2236
01:49:25,950 --> 01:49:29,730
>é esta região retangular,
então o código de máquina,

2237
01:49:29,730 --> 01:49:35,732
>os 0's e 1's que compõem seu programa são
carregados na parte superior da memória.

2238
01:49:35,732 --> 01:49:38,940
>E, novamente, superior, inferior, esquerda, direita,
não tem nenhum significado técnico fundamental.

2239
01:49:38,940 --> 01:49:40,470
>É apenas uma representação técnica.

2240
01:49:40,470 --> 01:49:42,960
>Mas ele vai para um local padrão.

2241
01:49:42,960 --> 01:49:45,700
>Abaixo disso estão todas
as suas variáveis globais.

2242
01:49:45,700 --> 01:49:48,250
>O mesmo ocorre com as constantes que
você coloca fora de suas funções.

2243
01:49:48,250 --> 01:49:50,500
>Isso vai acabar logo abaixo
do código de máquina,

2244
01:49:50,500 --> 01:49:53,340
>novamente, no topo da
memória do seu computador.

2245
01:49:53,340 --> 01:49:55,200
>Abaixo disso está o que é chamado de heap.

2246
01:49:55,200 --> 01:49:56,940
>E este é um termo técnico.

2247
01:49:56,940 --> 01:50:00,780
>E se refere a um grande
pedaço de memória que malloc

2248
01:50:00,780 --> 01:50:03,640
>usa para obter alguma memória sobressalente.

2249
01:50:03,640 --> 01:50:09,270
>Sempre que você chamar malloc, você recebe
o endereço de algum pedaço de memória

2250
01:50:09,270 --> 01:50:13,200
>sobre nesta região, abaixo do código de
máquina, abaixo de suas variáveis globais.

2251
01:50:13,200 --> 01:50:15,270
>E é uma zona grande.

2252
01:50:15,270 --> 01:50:19,120
>Mas o problema é que outras partes da sua
memória são usadas de maneira diferente.

2253
01:50:19,120 --> 01:50:24,570
>Na verdade, embora a pilha seja
considerada aqui embaixo, um pouco

2254
01:50:24,570 --> 01:50:28,830
>preocupantemente, a pilha é
considerada aqui para cima.

2255
01:50:28,830 --> 01:50:32,070
>Ou seja, quando você chama
malloc e pede memória,

2256
01:50:32,070 --> 01:50:35,670
>que é alocado aqui.

2257
01:50:35,670 --> 01:50:39,540
>Quando você chama uma função,
embora, essas funções

2258
01:50:39,540 --> 01:50:42,900
>usem o que é chamado de espaço de
pilha em vez de espaço de pilha.

2259
01:50:42,900 --> 01:50:48,450
>Então, sempre que você chamar uma função, main
ou swap ou strlang ou string compare

2260
01:50:48,450 --> 01:50:51,330
>ou qualquer uma das funções
que você usou até agora,

2261
01:50:51,330 --> 01:50:54,150
>seu computador irá armazenar
automaticamente qualquer

2262
01:50:54,150 --> 01:50:58,860
>das variáveis locais ou
parâmetros dessas funções aqui.

2263
01:50:58,860 --> 01:51:00,840
>Agora, este não é necessariamente
o melhor design,

2264
01:51:00,840 --> 01:51:02,550
>porque você pode ver as duas
setas apontando para uma

2265
01:51:02,550 --> 01:51:05,383
>outra - é como dois trens correndo
pelos trilhos um contra o outro.

2266
01:51:05,383 --> 01:51:07,268
>Coisas ruins podem acontecer.

2267
01:51:07,268 --> 01:51:09,060
>Felizmente, normalmente
temos memória suficiente

2268
01:51:09,060 --> 01:51:12,370
>para que essas duas coisas não colidam,
mas mais nisso daqui a pouco.

2269
01:51:12,370 --> 01:51:15,570
>Então, novamente, quando você chama funções,
a memória aqui embaixo é usada.

2270
01:51:15,570 --> 01:51:17,710
>Quando você usa malloc,
a memória aqui é usada.

2271
01:51:17,710 --> 01:51:19,710
>Agora, para minha função swap,
eu não estou usando malloc.

2272
01:51:19,710 --> 01:51:21,690
>Então eu não acho que tenho
que me preocupar com a pilha.

2273
01:51:21,690 --> 01:51:23,283
>E eu não tenho nenhuma variável global.

2274
01:51:23,283 --> 01:51:25,200
>E eu não me importo
com meu código de máquina.

2275
01:51:25,200 --> 01:51:27,240
>Eu só preciso saber se está
armazenado em algum lugar.

2276
01:51:27,240 --> 01:51:30,210
>Mas vamos considerar, então,
do que se trata a pilha.

2277
01:51:30,210 --> 01:51:32,670
>A pilha, é esse
tipo de lugar dinâmico

2278
01:51:32,670 --> 01:51:34,860
>onde a memória continua
sendo usada e reutilizada.

2279
01:51:34,860 --> 01:51:40,440
>Então, por exemplo, quando você chama main,
como você faria quando swap roda,

2280
01:51:40,440 --> 01:51:45,010
>main usa uma porção de memória na
parte inferior da imagem, se preferir.

2281
01:51:45,010 --> 01:51:47,910
>Portanto, as variáveis locais
principais, como x e y,

2282
01:51:47,910 --> 01:51:49,920
>acabam nesta parte inferior da memória.

2283
01:51:49,920 --> 01:51:53,790
>Quando você chama o swap, o swap usa um
pedaço de memória logo acima do principal,

2284
01:51:53,790 --> 01:51:58,350
>neste diagrama,
como as variáveis a e b e temp,

2285
01:51:58,350 --> 01:51:59,410
>para essa ação.

2286
01:51:59,410 --> 01:52:04,680
>E então, uma vez que o swap retorna e termina
a execução, aquele pedaço de memória

2287
01:52:04,680 --> 01:52:06,010
>vai embora.

2288
01:52:06,010 --> 01:52:07,230
>Agora, ele não desaparece.

2289
01:52:07,230 --> 01:52:09,610
>Obviamente, ainda há
memória física lá.

2290
01:52:09,610 --> 01:52:12,810
>Mas é aí que entramos na discussão
dos valores lixo novamente.

2291
01:52:12,810 --> 01:52:15,540
>Eles ainda são como Oscar
por toda parte.

2292
01:52:15,540 --> 01:52:18,600
>Você simplesmente não sabe, ou neste
ponto nem se importa, quais são os valores.

2293
01:52:18,600 --> 01:52:20,010
>Mas existem valores aí.
2294
01:52:20,010 --> 01:52:23,640
>E é por isso que, um momento atrás, quando
imprimi aquele array scores não inicializado,

2295
01:52:23,640 --> 01:52:26,970
>eu vi alguns valores
falsos, porque ainda

2296
01:52:26,970 --> 01:52:30,510
>vai haver 0's e 1's que
sobraram de antes.

2297
01:52:30,510 --> 01:52:31,750
>O problema, porém, é este.

2298
01:52:31,750 --> 01:52:35,070
>Vamos passar para esta
encarnação física de nossa memória

2299
01:52:35,070 --> 01:52:38,010
>e considero isso como sendo nossa
pilha, por isso está crescendo.

2300
01:52:38,010 --> 01:52:42,060
>E, se eu quiser ter duas
variáveis locais como eu faço, x e y,

2301
01:52:42,060 --> 01:52:47,400
>vamos prosseguir e pensar nesta linha
de memória aqui como sendo main,

2302
01:52:47,400 --> 01:52:48,870
>por exemplo, aqui.

2303
01:52:48,870 --> 01:52:51,630
>E vou prosseguir e substituir
todos esses valores de lixo

2304
01:52:51,630 --> 01:52:53,790
>com um valor real pelo qual me preocupo.

2305
01:52:53,790 --> 01:52:57,660
>E os valores reais que me interessam,
vamos chamar x e y, assim como

2306
01:52:57,660 --> 01:52:58,480
>antes.

2307
01:52:58,480 --> 01:53:01,020
>Portanto, cada um desses
Oscars tem um byte.

2308
01:53:01,020 --> 01:53:02,068
>Mas um int tem 4 bytes.

2309
01:53:02,068 --> 01:53:04,110
>Felizmente, de nossos
amigos da loja de presentes,

2310
01:53:04,110 --> 01:53:06,178
>temos esses blocos maiores
de tamanho inteiro.

2311
01:53:06,178 --> 01:53:08,220
>E vou prosseguir e
inserir isso aqui.

2312
01:53:08,220 --> 01:53:10,740
>E vamos pensar nisso,
em um momento, como x.

2313
01:53:10,740 --> 01:53:14,340
>E, vou prosseguir e
chamar esse x com um marcador.

2314
01:53:14,340 --> 01:53:17,760
>E então vou criar
outro número inteiro, um tamanho 4,

2315
01:53:17,760 --> 01:53:19,300
>e colocar aqui.

2316
01:53:19,300 --> 01:53:21,300
>E vamos pensar nisso como y.

2317
01:53:21,300 --> 01:53:23,940
>E lembre-se, como eu
inicializo esses valores?

2318
01:53:23,940 --> 01:53:27,690
>Bem, o valor 1,
inicialmente, e o valor 2.
2319
01:53:27,690 --> 01:53:29,370
>Mas então chamei a função swap.

2320
01:53:29,370 --> 01:53:32,160
>E a função swap tem
dois argumentos, a e b.

2321
01:53:32,160 --> 01:53:38,400
>E esses, por design, tornam-se cópias
de x e y, porque passei x vírgula y.

2322
01:53:38,400 --> 01:53:41,280
>E eu defini troca como uma vírgula b.

2323
01:53:41,280 --> 01:53:44,970
>Acho que o que preciso fazer,
fisicamente aqui, e agora

2324
01:53:44,970 --> 01:53:50,170
>pense nesta segunda linha de memória como
agora pertencente à função swap,

2325
01:53:50,170 --> 01:53:51,210
>não para main.

2326
01:53:51,210 --> 01:53:54,090
>E dentro desta segunda
linha de memória, eu irei

2327
01:53:54,090 --> 01:53:57,540
>pensar nisso como pertencendo a uma troca.

2328
01:53:57,540 --> 01:54:02,100
>E dentro da linha de troca, terei
outro inteiro de tamanho 4.

2329
01:54:02,100 --> 01:54:07,500
>E vamos chamar
este aqui de a.

2330
01:54:07,500 --> 01:54:10,350
>E então terei outro
pedaço de tamanho 4.

2331
01:54:10,350 --> 01:54:12,600
>E vamos chamar isso de b.
2332
01:54:12,600 --> 01:54:16,050
>E, novamente, porque esses são apenas os
argumentos, x vírgula y, caso contrário

2333
01:54:16,050 --> 01:54:20,760
>agora conhecido como vírgula b, copio
1 e 2 nesses valores.

2334
01:54:20,760 --> 01:54:22,770
>Mas swap tem uma terceira variável.

2335
01:54:22,770 --> 01:54:24,730
>Brian propôs uma variável temporária.

2336
01:54:24,730 --> 01:54:27,480
>Vou criar
mais quatro bytes,

2337
01:54:27,480 --> 01:54:30,210
>assim, livrando-se de qualquer
valor de lixo que esteja lá

2338
01:54:30,210 --> 01:54:34,260
>e configurá-la para uma chamada
de número inteiro tmp.

2339
01:54:34,260 --> 01:54:39,030
>Portanto, vou prosseguir e
chamar isso de tmp, T-M-P.

2340
01:54:39,030 --> 01:54:40,440
>E o que eu fiz primeiro?

2341
01:54:40,440 --> 01:54:43,845
>Defino tmp igual a a.

2342
01:54:43,845 --> 01:54:45,120
>Portanto, tmp é igual a a.

2343
01:54:45,120 --> 01:54:47,520
>Portanto, se a for 1, tmp será 1.

2344
01:54:47,520 --> 01:54:48,750
>Então o que eu fiz?
2345
01:54:48,750 --> 01:54:51,780
>Então fiz a é igual a b.

2346
01:54:51,780 --> 01:54:55,150
>Portanto, b é 2.

2347
01:54:55,150 --> 01:54:57,800
>a também é 2.

2348
01:54:57,800 --> 01:55:00,030
>E então, por último, o que eu fiz?

2349
01:55:00,030 --> 01:55:02,145
>Eu fiz b get tmp.

2350
01:55:02,145 --> 01:55:05,020
>Então eu tenho que ir em frente e
mudar isso para qualquer valor de tmp,

2351
01:55:05,020 --> 01:55:07,630
>que agora é o número 1.

2352
01:55:07,630 --> 01:55:10,150
>Então você pode ver que a troca
está correta na medida em que

2353
01:55:10,150 --> 01:55:12,655
> está trocando os valores de a e b.

2354
01:55:12,655 --> 01:55:16,690
>Mas no momento em que o swap
retorna, estes retornam

2355
01:55:16,690 --> 01:55:19,000
>a ser pensados como valores de lixo.

2356
01:55:19,000 --> 01:55:20,860
>Main ainda está no meio da execução.

2357
01:55:20,860 --> 01:55:22,300
>A troca não está mais em execução.

2358
01:55:22,300 --> 01:55:23,743
>Mas esses valores permanecem lá.
2359
01:55:23,743 --> 01:55:24,910
>Portanto, esses são valores de lixo.

2360
01:55:24,910 --> 01:55:27,850
>Acontece que sabemos o que são,
mas eles não são mais válidos,

2361
01:55:27,850 --> 01:55:32,560
>porque quando vou imprimir x e y
pela segunda vez, o que são x e y?

2362
01:55:32,560 --> 01:55:33,820
>Eles ainda são os mesmos.

2363
01:55:33,820 --> 01:55:37,870
>E isso quer dizer, quando você
escreve um código que leva argumentos

2364
01:55:37,870 --> 01:55:40,750
>e você passa argumentos
de uma função para outra,

2365
01:55:40,750 --> 01:55:43,930
>esses argumentos são copiados
de uma função para outra.

2366
01:55:43,930 --> 01:55:47,140
>E, x e y são
copiados em a e b.

2367
01:55:47,140 --> 01:55:51,670
>Portanto, seu código pode muito bem parecer
correto por estar alternando corretamente.

2368
01:55:51,670 --> 01:55:55,750
>Mas só está trocando corretamente
no contexto de troca,

2369
01:55:55,750 --> 01:55:58,370
>não tocar nos valores originais.

2370
01:55:58,370 --> 01:56:00,730
>Então, o que acho que precisamos
fazer, fundamentalmente,

2371
01:56:00,730 --> 01:56:06,130
>é reimplementar a troca
de forma que

2372
01:56:06,130 --> 01:56:10,450
>altere os valores de x e y.

2373
01:56:10,450 --> 01:56:11,500
>Mas como podemos fazer isso?

2374
01:56:11,500 --> 01:56:13,810
>Brian, se pudéssemos chamar alguém aqui.

2375
01:56:13,810 --> 01:56:18,340
>Como eu poderia mudar conceitualmente
minha implementação de swap

2376
01:56:18,340 --> 01:56:26,110
>para que de alguma forma me capacite a
alterar x e y, não alterar cópias de x e y?

2377
01:56:26,110 --> 01:56:28,570
>O que eu poderia passar para swap, Brian?

2378
01:56:28,570 --> 01:56:31,150
>BRIAN: Igor está sugerindo que
usemos ponteiros em seu lugar.

2379
01:56:31,150 --> 01:56:33,733
>DAVID MALAN: Sim, talvez a
questão principal aqui hoje.

2380
01:56:33,733 --> 01:56:36,010
>Mas as dicas parecem
nos dar uma solução.

2381
01:56:36,010 --> 01:56:38,170
>Se os ponteiros são
como um mapa do tesouro

2382
01:56:38,170 --> 01:56:41,500
>apontando para um endereço específico na memória
do seu computador, o que eu deveria

2383
01:56:41,500 --> 01:56:45,940
>fazer a partir do main para swap
é passar não x e y literalmente,
2384
01:56:45,940 --> 01:56:49,630
>mas por que não passo o
endereço de x e o endereço de y,

2385
01:56:49,630 --> 01:56:53,230
>para que a troca agora possa
ir para esses endereços

2386
01:56:53,230 --> 01:56:57,460
>e fazer o tipo de troca
que Brian fez pessoalmente.

2387
01:56:57,460 --> 01:57:02,050
>Então, dê à função uma espécie de mapa para
esses valores, ponteiros para esses valores,

2388
01:57:02,050 --> 01:57:03,560
>e depois vá para esses valores.

2389
01:57:03,560 --> 01:57:04,580
>Então, como posso fazer isso?

2390
01:57:04,580 --> 01:57:06,580
>Bem, o código tem que ser
um pouco diferente agora.

2391
01:57:06,580 --> 01:57:09,640
>Quando eu chamo swap desta vez,
o que eu preciso fazer

2392
01:57:09,640 --> 01:57:12,710
>é passar os endereços
dessas duas variáveis.

2393
01:57:12,710 --> 01:57:14,950
>Portanto, não sei necessariamente
quais são esses endereços.

2394
01:57:14,950 --> 01:57:16,900
>Mas pelo bem da história,
podemos apenas

2395
01:57:16,900 --> 01:57:21,340
>supor que este endereço,
por exemplo, é como 0x123.

2396
01:57:21,340 --> 01:57:25,142
>E então quatro bytes de distância
disso podem ser 0x127, por exemplo.

2397
01:57:25,142 --> 01:57:27,100
>Mas, novamente,
não importa o que seja.

2398
01:57:27,100 --> 01:57:29,440
>Mas têm endereços, x e y.

2399
01:57:29,440 --> 01:57:31,562
>Portanto, uma chamada de ponteiro
tende a ser muito grande.

2400
01:57:31,562 --> 01:57:33,520
>Então, precisávamos pegar
um pedaço maior de madeira,

2401
01:57:33,520 --> 01:57:35,590
>oito bytes que representam um ponteiro.

2402
01:57:35,590 --> 01:57:38,830
>E, na verdade, preciso usar um pouco
mais de memória no swap agora.

2403
01:57:38,830 --> 01:57:42,490
>Se eu declarar que a é,
não um número inteiro,

2404
01:57:42,490 --> 01:57:47,020
>mas um ponteiro para um int,
essa é uma variável int*,

2405
01:57:47,020 --> 01:57:49,330
>Eu poderia chamar isso de agora.

2406
01:57:49,330 --> 01:57:54,340
>E eu poderia armazenar, nela,
o endereço de x, como 0x123.

2407
01:57:54,340 --> 01:57:57,640
>Se eu mudar a definição
de b para ser

2408
01:57:57,640 --> 01:58:01,390
>não um inteiro, mas um
ponteiro para um inteiro,

2409
01:58:01,390 --> 01:58:04,810
>essa é outra int*, que
por acaso tem oito bytes.

2410
01:58:04,810 --> 01:58:07,780
>Vou usar um pouco mais de memória
para isso, mas tudo bem.

2411
01:58:07,780 --> 01:58:10,030
>E seu nome vai ser b agora.

2412
01:58:10,030 --> 01:58:13,600
>E vai conter 0x127.

2413
01:58:13,600 --> 01:58:15,820
>Ainda preciso de uma variável temporária.

2414
01:58:15,820 --> 01:58:18,650
>Ainda preciso de uma variável
temporária, mas tudo bem.

2415
01:58:18,650 --> 01:58:20,980
>Eu só preciso de quatro bytes
para isso, porque a variável

2416
01:58:20,980 --> 01:58:25,990
>em si só precisa armazenar um int, como
Brian o guardou temporariamente em um copo.

2417
01:58:25,990 --> 01:58:29,260
>Então, eu só preciso de quatro bytes
adicionais, como antes, para isso.

2418
01:58:29,260 --> 01:58:31,720
>E agora, vamos apenas considerar a lógica.

2419
01:58:31,720 --> 01:58:32,710
>Aqui está o main.

2420
01:58:32,710 --> 01:58:34,990
>E o swap agora está usando essas 3 -

2421
01:58:34,990 --> 01:58:36,550
>2 e 1/2 linhas de memória.
2422
01:58:36,550 --> 01:58:37,240
>E isso é bom.

2423
01:58:37,240 --> 01:58:39,640
>Está crescendo conforme eu propus.

2424
01:58:39,640 --> 01:58:41,860
>X está no endereço 0x123.

2425
01:58:41,860 --> 01:58:44,560
>y está no endereço 0x127.

2426
01:58:44,560 --> 01:58:48,370
>Portanto, a e b, proponho
conceitualmente, como Igor propôs,

2427
01:58:48,370 --> 01:58:52,280
>armazene os endereços de
a, x e y, respectivamente.

2428
01:58:52,280 --> 01:58:55,060
>E agora meu código, eu
acho, precisa dizer isso.

2429
01:58:55,060 --> 01:59:00,025
>Vá e armazene, na variável tmp, o
que quer que esteja no endereço a.

2430
01:59:00,025 --> 01:59:02,650
>Então você pode pensar nisso
como uma flecha aqui embaixo.

2431
01:59:02,650 --> 01:59:03,910
>Siga a seta, OK.

2432
01:59:03,910 --> 01:59:06,010
>O que está no endereço 0x123?

2433
01:59:06,010 --> 01:59:06,910
>O número 1.

2434
01:59:06,910 --> 01:59:09,250
>Então colocamos um no tmp, assim como antes.

2435
01:59:09,250 --> 01:59:10,310
>Então o que vamos fazer?

2436
01:59:10,310 --> 01:59:13,540
>Bem, agora, vou prosseguir e
mudar, não o valor de um,

2437
01:59:13,540 --> 01:59:18,010
>mas vou mudar o que
está no local para ser

2438
01:59:18,010 --> 01:59:24,790
>o que quer que esteja no local em b, que é
uma seta apontando para baixo aqui, 0x127.

2439
01:59:24,790 --> 01:59:27,850
>Vou mudar este 1,
agora, para um 2.

2440
01:59:27,850 --> 01:59:30,910
>E a terceira e última etapa,
lembre-se, é para mim, agora,

2441
01:59:30,910 --> 01:59:37,150
>ir, não para b, mas para ir para
onde b aponta, que por acaso é y,

2442
01:59:37,150 --> 01:59:42,440
>e mudar para o valor de tmp, que
é claro, está aqui em cima.

2443
01:59:42,440 --> 01:59:45,430
>E neste ponto da história,
ainda são apenas três linhas de código.

2444
01:59:45,430 --> 01:59:47,380
>São diferentes tipos
de linhas de código.

2445
01:59:47,380 --> 01:59:48,950
>São três linhas de código.

2446
01:59:48,950 --> 01:59:52,180
>Mas quando swap termina a execução,
observe o que fizemos.

2447
01:59:52,180 --> 01:59:55,190
>Trocamos x e y com
sucesso, permitindo

2448
01:59:55,190 --> 01:59:59,270
>que swap vá para esses endereços em
vez de apenas obter ingenuamente

2449
01:59:59,270 --> 02:00:02,180
>cópias dos valores nele contidos.

2450
02:00:02,180 --> 02:00:05,150
>Agora, embora este código
pareça um pouco enigmático,

2451
02:00:05,150 --> 02:00:10,820
>é uma aplicação
da lógica que vimos até agora.

2452
02:00:10,820 --> 02:00:13,860
>Vou prosseguir e voltar para a
minha versão antiga com erros.

2453
02:00:13,860 --> 02:00:15,860
>E vou mudar a
definição de swap

2454
02:00:15,860 --> 02:00:19,190
>para dizer que não são necessários
dois inteiros, a e b, mas dois

2455
02:00:19,190 --> 02:00:20,810
>ponteiros para inteiros a e b.

2456
02:00:20,810 --> 02:00:24,080
>E a forma como você declara um ponteiro, lembre,
é o tipo de variável

2457
02:00:24,080 --> 02:00:26,767
>que você aponta para, seguida por um
asterisco e então o nome dela.

2458
02:00:26,767 --> 02:00:28,850
>E nós não vimos isso,
reconhecidamente, no contexto

2459
02:00:28,850 --> 02:00:31,550
>de uma função que leva parâmetros ainda.
2460
02:00:31,550 --> 02:00:33,170
>Mas é simplesmente isso.

2461
02:00:33,170 --> 02:00:34,610
>Eu adicionei os asteriscos.

2462
02:00:34,610 --> 02:00:40,040
>Aqui embaixo, preciso dizer,
armazenar em tmp, o que quer que esteja em a.

2463
02:00:40,040 --> 02:00:41,870
>Como faço para expressar "vá para a"?

2464
02:00:41,870 --> 02:00:43,520
>Basta adicionar uma asterisco aqui.

2465
02:00:43,520 --> 02:00:46,880
>Como expresso "vá para a" e coloco
o que quer que esteja em b?

2466
02:00:46,880 --> 02:00:48,500
>Eu adiciono asteriscos lá.

2467
02:00:48,500 --> 02:00:51,560
>Como posso dizer para ir para b e
armazenar o que quer que esteja em tmp?

2468
02:00:51,560 --> 02:00:53,190
>Eu adiciono uma asterisco aqui.

2469
02:00:53,190 --> 02:00:55,520
>Portanto, tmp é um número inteiro simples.

2470
02:00:55,520 --> 02:00:57,380
>É apenas um copo vazio como o de Brian.

2471
02:00:57,380 --> 02:00:58,620
>Não há nada sofisticado aí.

2472
02:00:58,620 --> 02:01:00,650
>Portanto, não precisamos de asteriscos em torno de tmp.

2473
02:01:00,650 --> 02:01:04,970
>Mas agora preciso mudar a forma
como estou usando a e b,

2474
02:01:04,970 --> 02:01:08,330
>porque agora são endereços
aonde eu quero ir.

2475
02:01:08,330 --> 02:01:12,140
>Não há necessidade de endereço
do operador neste contexto.

2476
02:01:12,140 --> 02:01:14,330
>Mas aqui em cima, vou
precisar fazer uma mudança.

2477
02:01:14,330 --> 02:01:16,380
>Eu preciso mudar o protótipo
para corresponder.

2478
02:01:16,380 --> 02:01:18,200
>Então isso é copiar e colar.

2479
02:01:18,200 --> 02:01:23,120
>Mas aposto que você pode imaginar
o que, por último, precisa mudar.

2480
02:01:23,120 --> 02:01:26,750
>Ao chamar swap, não quero passar
ingenuamente x e y, porque, novamente,

2481
02:01:26,750 --> 02:01:27,980
> serão copiadas.

2482
02:01:27,980 --> 02:01:32,000
>Eu quero passar o endereço
de x e o endereço de y,

2483
02:01:32,000 --> 02:01:35,690
>então essa troca agora tem uma
espécie de acesso especial

2484
02:01:35,690 --> 02:01:38,750
>para o conteúdo desses
locais na memória

2485
02:01:38,750 --> 02:01:42,740
>para que possa
fazer algumas alterações.
2486
02:01:42,740 --> 02:01:47,780
>E que, se eu recompilar este
programa agora, make swap, e eu

2487
02:01:47,780 --> 02:01:50,390
>.swap, e cruzo meus dedos.
Voila.

2488
02:01:50,390 --> 02:01:53,855
>Agora, eu troquei com sucesso
as linhas de código.

2489
02:01:53,855 --> 02:01:55,730
>Então, na semana passada, se você
estivesse se perguntando, talvez,

2490
02:01:55,730 --> 02:01:58,250
>por que não mostramos como
fazer a troca, poderíamos ter feito.

2491
02:01:58,250 --> 02:01:59,900
>E não precisamos de uma função especial.

2492
02:01:59,900 --> 02:02:03,200
>Você não precisa necessariamente de
ponteiros se fizermos tudo isso no main.

2493
02:02:03,200 --> 02:02:06,470
>Mas estou tentando introduzir
uma abstração, esta função que

2494
02:02:06,470 --> 02:02:09,740
>troca exatamente como o Brian
trocou os copos por nós.

2495
02:02:09,740 --> 02:02:12,650
>E para passar valores de
uma função para outra,

2496
02:02:12,650 --> 02:02:15,990
>você precisa entender o que está
acontecendo na memória do seu computador

2497
02:02:15,990 --> 02:02:18,830
>para que você possa passar
pequenas migalhas de pão novamente,
2498
02:02:18,830 --> 02:02:23,330
>mapas do tesouro para esses locais e memórias,
mais uma vez, graças a essas coisas

2499
02:02:23,330 --> 02:02:25,100
>chamadas ponteiros.

2500
02:02:25,100 --> 02:02:27,770
>Tudo bem, deixe-me
propor e enfatizar,

2501
02:02:27,770 --> 02:02:30,770
>então, que este desenho
da pilha estando no topo,

2502
02:02:30,770 --> 02:02:33,200
>onde malloc usa memória
e a pilha sendo

2503
02:02:33,200 --> 02:02:35,540
>na parte inferior, onde suas
próprias funções usam memória,

2504
02:02:35,540 --> 02:02:37,730
>este é um problema claramente
esperando para acontecer.

2505
02:02:37,730 --> 02:02:39,460
>E esses problemas têm nomes.

2506
02:02:39,460 --> 02:02:41,210
>E alguns de vocês que
já programaram antes

2507
02:02:41,210 --> 02:02:45,230
>pode conhecer alguns desses termos,
heap overflow, estouro de pilha ou stack overflow.

2508
02:02:45,230 --> 02:02:48,650
>E, muitos de vocês devem conhecer
stackoverflow.com apenas como um site.

2509
02:02:48,650 --> 02:02:50,840
>Bem, há uma história
de origem em seu nome.
2510
02:02:50,840 --> 02:02:56,240
>Um estouro de pilha se refere ao processo
de chamar uma função tantas vezes

2511
02:02:56,240 --> 02:02:58,550
>que transborda a pilha.

2512
02:02:58,550 --> 02:03:00,320
>Ou seja, toda vez que
você chama a função,

2513
02:03:00,320 --> 02:03:04,950
>como eu fiz aqui, você usa cada vez mais
linhas, por assim dizer, de memória.

2514
02:03:04,950 --> 02:03:07,730
>E se você chamar tantas
funções de novo e de novo,

2515
02:03:07,730 --> 02:03:11,690
>eventualmente, você pode muito bem correr
sobre a área da memória chamada heap.

2516
02:03:11,690 --> 02:03:14,090
>E nesse ponto, seu
programa irá travar.

2517
02:03:14,090 --> 02:03:18,950
>Não há solução fundamental para esse
problema além de não fazer isso.

2518
02:03:18,950 --> 02:03:20,420
>Não use muita memória.

2519
02:03:20,420 --> 02:03:21,680
>Mas isso pode ser difícil de fazer.

2520
02:03:21,680 --> 02:03:24,138
>E, esse é um dos
perigos da programação hoje.

2521
02:03:24,138 --> 02:03:27,800
>E podemos induzir isso um
pouco deliberadamente.

2522
02:03:27,800 --> 02:03:30,620
>E, na verdade, pensei que
poderíamos revisitar, por exemplo,

2523
02:03:30,620 --> 02:03:34,220
>onde paramos com o Mario da última
vez, que foi essa foto aqui.

2524
02:03:34,220 --> 02:03:37,580
>Lembre-se de que esta era
uma pirâmide, é claro,

2525
02:03:37,580 --> 02:03:40,400
>mais simples do que aquela com a qual
você pode ter brincado nos problemas da semana 0.

2526
02:03:40,400 --> 02:03:44,360
>Mas é uma pirâmide recursiva em que você
pode definir uma pirâmide de altura 4,

2527
02:03:44,360 --> 02:03:47,690
>em termos de uma pirâmide de altura 3,
em termos de uma pirâmide de altura 2

2528
02:03:47,690 --> 02:03:48,380
>e uma altura 1.

2529
02:03:48,380 --> 02:03:52,580
>E, eu construí isso na semana
passada usando esses mesmos blocos.

2530
02:03:52,580 --> 02:03:56,180
>Bem, você pode implementar
a pirâmide do Mário assim

2531
02:03:56,180 --> 02:03:57,660
>de algumas maneiras diferentes.

2532
02:03:57,660 --> 02:04:01,160
>Uma deles é usar apenas a iteração
de estilo da semana um, usando um loop.

2533
02:04:01,160 --> 02:04:03,890
>E, na verdade, deixe-me ir em frente
e criar uma solução rápida que

2534
02:04:03,890 --> 02:04:05,340
>faz exatamente isso.
2535
02:04:05,340 --> 02:04:07,730
>Eu vou chamar isso de mario.c.

2536
02:04:07,730 --> 02:04:10,610
>E vou prosseguir e
incluir cs50.h.

2537
02:04:10,610 --> 02:04:12,290
>Portanto, podemos usar uma de nossas funções get.

2538
02:04:12,290 --> 02:04:14,300
>Vou usar o padrão io ponto h.

2539
02:04:14,300 --> 02:04:16,160
>E vou fazer o main void.

2540
02:04:16,160 --> 02:04:18,590
>E tudo que eu quero fazer
é imprimir esta pirâmide.

2541
02:04:18,590 --> 02:04:20,340
>Mas quero perguntar
ao usuário a altura.

2542
02:04:20,340 --> 02:04:23,090
>Portanto, vou dizer que int
height é igual a get int.

2543
02:04:23,090 --> 02:04:26,870
>E pediremos ao usuário a altura,
assim como você fez para o conjunto de problemas 1.

2544
02:04:26,870 --> 02:04:30,000
>E então vou seguir em frente e
desenhar uma pirâmide dessa altura.

2545
02:04:30,000 --> 02:04:31,340
>Agora, o desenho não existe.

2546
02:04:31,340 --> 02:04:32,030
>Mas tudo bem.

2547
02:04:32,030 --> 02:04:34,735
>Vou seguir em frente e desenhar isso
agora, implementar o desenho sozinho.
2548
02:04:34,735 --> 02:04:36,860
>Não precisa retornar um
valor, porque estou apenas

2549
02:04:36,860 --> 02:04:38,273
>imprimindo coisas na tela.

2550
02:04:38,273 --> 02:04:40,190
>A função é chamada de draw,
e vai pegar

2551
02:04:40,190 --> 02:04:42,710
>uma entrada chamada h, por
exemplo. h para altura,

2552
02:04:42,710 --> 02:04:45,080
>mas eu poderia chamar seu
argumento do que eu quiser.

2553
02:04:45,080 --> 02:04:48,650
>E então eu vou apenas fazer
isso, para int eu recebo 1,

2554
02:04:48,650 --> 02:04:52,850
>i menor ou igual a h, i++.

2555
02:04:52,850 --> 02:04:56,170
>E, dentro disso, é aqui que você deve se
lembrar, do conjunto de problemas um,

2556
02:04:56,170 --> 02:04:58,700
>descobriu que um loop aninhado é útil.

2557
02:04:58,700 --> 02:05:04,150
>Vou fazer int j gets 1,
j menor ou igual a i, j++.

2558
02:05:04,150 --> 02:05:08,178
>Isso será semelhante, mas não
idêntico a mais confortável

2559
02:05:08,178 --> 02:05:09,970
>versão de
Mario do passado,

2560
02:05:09,970 --> 02:05:13,240
>porque esta pirâmide é moldada
em uma direção diferente.

2561
02:05:13,240 --> 02:05:15,610
>Agora, você imprime um hash.

2562
02:05:15,610 --> 02:05:17,830
>E então agora eu vou
imprimir uma nova linha aqui.

2563
02:05:17,830 --> 02:05:19,570
>Então eu fiz isso super rápido.

2564
02:05:19,570 --> 02:05:21,880
>Mas logicamente, o que
estou fazendo está iterando

2565
02:05:21,880 --> 02:05:29,710
>em todas as linhas, de 1 a h, portanto,
linhas 1, 2, 3, 4, por exemplo.

2566
02:05:29,710 --> 02:05:34,210
>E então, em cada linha, estou
deliberadamente iterando de 1 a i.

2567
02:05:34,210 --> 02:05:37,870
>Então, imprimo 1, 2, 3 e 4.

2568
02:05:37,870 --> 02:05:39,640
>E, novamente, posso zerar o índice.

2569
02:05:39,640 --> 02:05:44,170
>Acho que, neste contexto, é mais amigável,
mais inteligível para mim

2570
02:05:44,170 --> 02:05:46,660
>indexar de 1, totalmente
razoável se você pensar

2571
02:05:46,660 --> 02:05:48,310
>que há um argumento de design atraente.

2572
02:05:48,310 --> 02:05:50,030
>Então agora eu vou fazer make Mario.

2573
02:05:50,030 --> 02:05:51,520
>Ah, droga.

2574
02:05:51,520 --> 02:05:53,980
>Oh, eu perdi meu protótipo.

2575
02:05:53,980 --> 02:05:55,870
>Então observe, não está entendendo
draw.

2576
02:05:55,870 --> 02:05:58,900
>Então, a solução para isso
é mover toda a função

2577
02:05:58,900 --> 02:06:02,980
>ou, como já pregamos, apenas
colocar seu protótipo no topo.

2578
02:06:02,980 --> 02:06:05,050
>Vamos recompilar Mario.

2579
02:06:05,050 --> 02:06:06,430
>OK, agora com sucesso.

2580
02:06:06,430 --> 02:06:08,710
>Mario, vamos fazer uma
altura de 4 e voila.

2581
02:06:08,710 --> 02:06:11,350
>Agora, eu consegui, relativamente
simples - embora eu certamente

2582
02:06:11,350 --> 02:06:13,600
>fiz isso mais rápido do que
você faria sem alguma prática -

2583
02:06:13,600 --> 02:06:15,760
>na implementação da pirâmide do Mário.

2584
02:06:15,760 --> 02:06:17,980
>Mas é aqui que as coisas
ficam mais legais.

2585
02:06:17,980 --> 02:06:20,800
>Vamos estipular que essa é uma
solução iterativa correta, mesmo
2586
02:06:20,800 --> 02:06:24,970
>se isso pode exigir um certo número
de etapas ou tentativa e erro

2587
02:06:24,970 --> 02:06:28,180
>para obter esse código baseado
em loop iterativo correto.

2588
02:06:28,180 --> 02:06:30,580
>Vou mudar isso,
agora, para ser recursivo.

2589
02:06:30,580 --> 02:06:34,510
>E lembre-se, uma função recursiva
é aquela que chama a si mesma.

2590
02:06:34,510 --> 02:06:37,660
>Como você imprime uma pirâmide de altura h?

2591
02:06:37,660 --> 02:06:41,980
>Bem, lembre-se de que você imprime
uma pirâmide de altura h menos 1,

2592
02:06:41,980 --> 02:06:45,340
>e, em seguida, você imprime
mais uma linha de blocos.

2593
02:06:45,340 --> 02:06:48,970
>Então, deixe-me interpretar literalmente.
para int, eu chego a zero.

2594
02:06:48,970 --> 02:06:51,550
>i é menor que h, i++.

2595
02:06:51,550 --> 02:06:54,550
>Eu vou imprimir
essa linha extra de tijolos

2596
02:06:54,550 --> 02:06:58,480
>assim, seguido por uma nova linha.

2597
02:06:58,480 --> 02:07:00,260
>Então agora, eu fiz isso meio rápido.

2598
02:07:00,260 --> 02:07:01,340
>Mas o que estou fazendo aqui?
2599
02:07:01,340 --> 02:07:06,520
>Bem, se a altura for igual a 1,
quero que este loop itere uma vez.

2600
02:07:06,520 --> 02:07:10,760
>Se a altura fosse igual a 2, eu queria
iterar duas vezes, 3 e assim por diante.

2601
02:07:10,760 --> 02:07:14,260
>Então eu acho que, usando minha técnica de
indexação zero aqui, isso vai funcionar também.

2602
02:07:14,260 --> 02:07:17,080
>Mas se você preferir, eu certamente
poderia mudar isso para 1

2603
02:07:17,080 --> 02:07:18,638
>e alterar este 2.

2604
02:07:18,638 --> 02:07:19,930
>Mas vou ...

2605
02:07:19,930 --> 02:07:20,500
>não.

2606
02:07:20,500 --> 02:07:23,350
>Neste caso, quero deixar
assim, índice zero,

2607
02:07:23,350 --> 02:07:25,450
>exatamente como fazemos normalmente.

2608
02:07:25,450 --> 02:07:29,200
>Tudo bem, deixe-me compilar
isso, make Mario.

2609
02:07:29,200 --> 02:07:31,870
>OK, oops, interessante.

2610
02:07:31,870 --> 02:07:34,940
>Todos os caminhos por meio dessa
função serão chamados a si próprios.

2611
02:07:34,940 --> 02:07:37,780
>Então o clang é ser inteligente
aqui, por meio do qual,

2612
02:07:37,780 --> 02:07:42,260
>vejo que em minha função draw,
estou chamando minha função draw.

2613
02:07:42,260 --> 02:07:44,358
>E esse é um processo que nunca muda.

2614
02:07:44,358 --> 02:07:46,150
>Na verdade, deixe-me ver se
eu posso substituir isso.

2615
02:07:46,150 --> 02:07:51,310
>Vamos usar o clang manualmente e compilar
um programa chamado mario usando mario.c.

2616
02:07:51,310 --> 02:07:53,140
>Agora eu vou criar um link no cs50.

2617
02:07:53,140 --> 02:07:55,960
>Portanto, estou usando nossa sintaxe
old school da segunda semana.

2618
02:07:55,960 --> 02:07:56,980
>OK, compilado.

2619
02:07:56,980 --> 02:07:58,270
>E por que isso compilou?

2620
02:07:58,270 --> 02:08:01,872
>Bem, make é, novamente, um programa
que usa o clang do compilador.

2621
02:08:01,872 --> 02:08:05,080
>E configuramos o make para ser um
pouco mais amigável e um pouco mais

2622
02:08:05,080 --> 02:08:07,450
>protetor, ativando recursos especiais

2623
02:08:07,450 --> 02:08:09,250
>onde detectamos problemas como esse.

2624
02:08:09,250 --> 02:08:12,730
>Ao usar o clang diretamente agora, estou
desativando essas verificações especiais.

2625
02:08:12,730 --> 02:08:16,840
>E veja o que acontece quando eu rodo o Mario
agora para a altura de 4, por exemplo.

2626
02:08:16,840 --> 02:08:18,730
>E é isso, travou.

2627
02:08:18,730 --> 02:08:20,500
>Nem mesmo imprimiu nada.

2628
02:08:20,500 --> 02:08:21,953
>Ele travou muito rapidamente.

2629
02:08:21,953 --> 02:08:25,120
>E, novamente, uma falha de segmentação significa
que você tocou na memória que não deveria.

2630
02:08:25,120 --> 02:08:26,200
>Então, o que está acontecendo?

2631
02:08:26,200 --> 02:08:30,302
>Bem, se você pensar nesta memória como uma
representação de parada principal, mas então desenhar,

2632
02:08:30,302 --> 02:08:33,610
>desenhar, desenhar, desenhar, desenhar, desenhar.

2633
02:08:33,610 --> 02:08:37,540
>Se todas as suas chamadas para draw
chamam draw de novo,

2634
02:08:37,540 --> 02:08:39,070
>por que isso iria parar?

2635
02:08:39,070 --> 02:08:41,590
>Não pareceria parar aqui.

2636
02:08:41,590 --> 02:08:45,070
>Portanto, parece que está faltando um detalhe
importante em minha versão recursiva.

2637
02:08:45,070 --> 02:08:45,670
>Você sabe o que é?
2638
02:08:45,670 --> 02:08:51,130
>Se não houver nada para desenhar, se a altura
for igual a 0, deixe-me continuar, então,

2639
02:08:51,130 --> 02:08:54,260
>e voltar imediatamente.

2640
02:08:54,260 --> 02:08:57,250
>Caso contrário, vou seguir em
frente e desenhar parte da pirâmide

2641
02:08:57,250 --> 02:08:59,260
>e, em seguida, adicionar a nova linha.

2642
02:08:59,260 --> 02:09:02,110
>Então, você precisa desse chamado
caso básico, que você literalmente

2643
02:09:02,110 --> 02:09:05,410
>escolhe igualar a algum valor simples,
como altura de 0, altura de 1,

2644
02:09:05,410 --> 02:09:10,880
>qualquer valor codificado permanentemente, de modo
que, eventualmente, draw não chame a si mesmo.

2645
02:09:10,880 --> 02:09:15,040
>Então, deixe-me recompilar
isso com clang ou make.

2646
02:09:15,040 --> 02:09:18,430
>Vamos executá-lo novamente, altura de 4 e voila.

2647
02:09:18,430 --> 02:09:20,680
>Ainda está funcionando
como a versão interna,

2648
02:09:20,680 --> 02:09:22,340
>mas agora está usando recursão.

2649
02:09:22,340 --> 02:09:24,250
>Então aqui está um tipo de questão de design.

2650
02:09:24,250 --> 02:09:26,020
>A iteração é melhor do que a recursão?
2651
02:09:26,020 --> 02:09:26,680
>Depende.

2652
02:09:26,680 --> 02:09:28,270
>A iteração sempre funcionará.

2653
02:09:28,270 --> 02:09:32,290
>Ao usar a versão iterativa,
eu nunca vou estourar a pilha

2654
02:09:32,290 --> 02:09:33,140
>e acertar heap.

2655
02:09:33,140 --> 02:09:33,640
>Por quê?

2656
02:09:33,640 --> 02:09:35,723
>Porque não estou chamando
funções de novo e de novo.

2657
02:09:35,723 --> 02:09:38,410
>Há apenas main e
uma invocação de draw.

2658
02:09:38,410 --> 02:09:42,550
>Mas com a versão recursiva,
é uma forma legal e poderosa

2659
02:09:42,550 --> 02:09:43,270
>para fazer coisas.

2660
02:09:43,270 --> 02:09:45,610
>Tipo, eu posso desenhar para
você uma pirâmide de altura h.

2661
02:09:45,610 --> 02:09:48,370
>Vamos desenhar uma
pirâmide de altura h menos 1,

2662
02:09:48,370 --> 02:09:49,750
>e então adicionarei uma linha.

2663
02:09:49,750 --> 02:09:54,950
>É um tipo de argumento inteligente e cíclico
que funciona de maneira muito elegante.
2664
02:09:54,950 --> 02:09:56,150
>Mas existe um perigo.

2665
02:09:56,150 --> 02:10:00,830
>E, embora este caso básico
garanta que não durará eternamente,

2666
02:10:00,830 --> 02:10:05,180
>poderia demorar muito - talvez
vamos tentar 10.000 invocações.

2667
02:10:05,180 --> 02:10:06,290
>Então funcionou bem.

2668
02:10:06,290 --> 02:10:07,820
>É um pouco lento.

2669
02:10:07,820 --> 02:10:09,320
>Estou perdendo o controle do meu teclado.

2670
02:10:09,320 --> 02:10:10,730
>Portanto, o Ctrl C é seu amigo.

2671
02:10:10,730 --> 02:10:12,050
>Vamos tentar mais uma vez.

2672
02:10:12,050 --> 02:10:16,700
>Eu vou fazer algo
como 2 bilhões para ver se funciona.

2673
02:10:16,700 --> 02:10:17,540
>Explodiu.

2674
02:10:17,540 --> 02:10:19,110
>Portanto, mesmo isso não funciona.

2675
02:10:19,110 --> 02:10:21,710
>Portanto, há esse perigo inerente
com a recursão, por meio da qual,

2676
02:10:21,710 --> 02:10:25,010
>embora tenha nos capacitado na semana passada para
resolver um problema de forma ainda mais eficiente

2677
02:10:25,010 --> 02:10:29,810
>com o merge sort, meio que tivemos sorte,
em que não estávamos tentando coisas insanamente

2678
02:10:29,810 --> 02:10:33,080
>grandes na prateleira de Brian, porque
parece que se você usar recursão

2679
02:10:33,080 --> 02:10:35,330
>e chamar a si mesmo de novo e
de novo e de novo e de novo,

2680
02:10:35,330 --> 02:10:40,340
>mesmo que finitamente, mas muitas vezes, você pode
tocar na memória que não deveria.

2681
02:10:40,340 --> 02:10:42,290
>E qual é a solução aqui?

2682
02:10:42,290 --> 02:10:44,510
>Infelizmente, é "Não faça isso".

2683
02:10:44,510 --> 02:10:48,020
>Projete seus algoritmos, escolha
suas entradas de tal forma

2684
02:10:48,020 --> 02:10:49,560
>que simplesmente não exista esse risco.

2685
02:10:49,560 --> 02:10:51,800
>E usaremos a recursão
novamente em algumas semanas

2686
02:10:51,800 --> 02:10:54,800
>no momento em que olhamos para estruturas
de dados mais sofisticadas.

2687
02:10:54,800 --> 02:10:56,600
>Mas, novamente,
sempre há essa troca.

2688
02:10:56,600 --> 02:10:58,725
>Só porque você pode criar
algo um pouco mais

2689
02:10:58,725 --> 02:11:03,120
>elegantemente não significa necessariamente
que sempre funcionará para você.
2690
02:11:03,120 --> 02:11:06,560
>Mas, mais comumente, você provavelmente
terá outros problemas também?

2691
02:11:06,560 --> 02:11:08,540
>Existe algo chamado
estouro de buffer.

2692
02:11:08,540 --> 02:11:10,880
>E você certamente tropeçará
nisso nas próximas semanas.

2693
02:11:10,880 --> 02:11:13,610
>Um estouro de buffer é
quando você aloca um array

2694
02:11:13,610 --> 02:11:15,590
>e vai muito além do fim.

2695
02:11:15,590 --> 02:11:18,650
>Ou você usa malloc e,
no entanto, vai mais longe

2696
02:11:18,650 --> 02:11:21,020
>do que o final do pedaço de
memória que você alocou.

2697
02:11:21,020 --> 02:11:25,010
>Um buffer é um pedaço de memória,
por assim dizer, que você pode usar

2698
02:11:25,010 --> 02:11:25,550
>enquanto couber.

2699
02:11:25,550 --> 02:11:30,230
>O estouro do buffer significa ir
além dos limites desse array.

2700
02:11:30,230 --> 02:11:32,930
>Você pode usar-- você está
usando, agora, vídeo.

2701
02:11:32,930 --> 02:11:35,125
>Você deve conhecer a frase
buffering de vídeos,
2702
02:11:35,125 --> 02:11:37,250
>como o buffer
irritante da Netflix,

2703
02:11:37,250 --> 02:11:39,050
>porque há um ícone
giratório ou algo assim.

2704
02:11:39,050 --> 02:11:40,700
>Bem, isso significa exatamente isso.

2705
02:11:40,700 --> 02:11:44,090
>Um buffer, no contexto de
YouTube ou Zoom ou Netflix,

2706
02:11:44,090 --> 02:11:46,910
>significa algum pedaço de
memória que foi recuperado

2707
02:11:46,910 --> 02:11:49,880
>via malloc ou alguma ferramenta
semelhante que é preenchida

2708
02:11:49,880 --> 02:11:52,580
>com bytes compreendendo seu vídeo.

2709
02:11:52,580 --> 02:11:56,210
>E é finito, por isso você só
pode armazenar alguns segundos

2710
02:11:56,210 --> 02:11:59,520
>ou minutos de vídeo antes,
eventualmente, se você estiver offline,

2711
02:11:59,520 --> 02:12:01,220
>você fica sem conteúdo de vídeo para assistir.

2712
02:12:01,220 --> 02:12:02,930
>E o ícone idiota aparece, e você pode

2713
02:12:02,930 --> 02:12:07,680
>não ver mais nada, porque um buffer é um
pedaço de memória, um array de memória.

2714
02:12:07,680 --> 02:12:12,830
>E se a Netflix, o Google ou outros
implementassem seus códigos de maneira insegura,

2715
02:12:12,830 --> 02:12:16,740
>eles poderiam muito bem ir muito
além dessa fronteira.

2716
02:12:16,740 --> 02:12:22,070
>Com tudo isso dito, vamos considerar,
em alguns de nossos minutos finais

2717
02:12:22,070 --> 02:12:26,000
>aqui hoje, apenas o que mais
recebemos dessas treino de iniciação,

2718
02:12:26,000 --> 02:12:28,830
>porque queremos retirá-las
na maioria para você andar sozinho.

2719
02:12:28,830 --> 02:12:30,890
>Portanto, a biblioteca
CS50 não fornece apenas

2720
02:12:30,890 --> 02:12:33,855
>esta abstração de um tipo
de string, que novamente,

2721
02:12:33,855 --> 02:12:35,480
>não oferece nenhuma nova funcionalidade.

2722
02:12:35,480 --> 02:12:38,600
>Strings em C existem,
apenas não por esse nome.

2723
02:12:38,600 --> 02:12:40,850
>Eles são conhecidas mais
apropriadamente como char*.

2724
02:12:40,850 --> 02:12:43,730
>Mas todas essas funções
na biblioteca CS50

2725
02:12:43,730 --> 02:12:49,490
>podem ser implementadas com outras
funções C que não eram do CS50,

2726
02:12:49,490 --> 02:12:51,740
>ou seja, usando um chamado scanf.
2727
02:12:51,740 --> 02:12:54,260
>Mas você vai ver,
imediatamente, alguns dos perigos

2728
02:12:54,260 --> 02:12:57,980
>de usar algo como scanf,
que é uma função old school.

2729
02:12:57,980 --> 02:13:01,280
>Não foi projetada para ser autodefensivo
como a biblioteca do CS50.

2730
02:13:01,280 --> 02:13:03,510
>E assim é muito fácil cometer erros.

2731
02:13:03,510 --> 02:13:06,650
>vou continuar, por
exemplo, e criar um arquivo

2732
02:13:06,650 --> 02:13:09,860
>chamado scanf.c, apenas para
demonstrar esta função.

2733
02:13:09,860 --> 02:13:13,200
>Não vou usar a biblioteca CS50,
apenas o padrão io ponto h.

2734
02:13:13,200 --> 02:13:15,470
>E vou criar
int main void.

2735
02:13:15,470 --> 02:13:18,110
>Vou criar uma variável x.

2736
02:13:18,110 --> 02:13:21,260
>E vou prosseguir e imprimir
"x:"

2737
02:13:21,260 --> 02:13:24,060
>assim como a função get int do CS50.

2738
02:13:24,060 --> 02:13:25,940
>E então vou chamar o scanf.

2739
02:13:25,940 --> 02:13:30,170
>E vou prosseguir e dizer, digitalize, no
teclado do usuário, um número inteiro,

2740
02:13:30,170 --> 02:13:33,708
>e armazene-o no local de x.

2741
02:13:33,708 --> 02:13:35,750
>Então, vou prosseguir e
imprimir, novamente,

2742
02:13:35,750 --> 02:13:40,340
>x, e dois pontos e uma \ %i \n.

2743
02:13:40,340 --> 02:13:41,420
>E vou imprimir x.

2744
02:13:41,420 --> 02:13:42,830
>Então, o que está acontecendo aqui?

2745
02:13:42,830 --> 02:13:46,580
>Na linha 5, estou declarando uma variável
chamada x, assim como na primeira semana.

2746
02:13:46,580 --> 02:13:49,220
>Linha 6, apenas usando printf,
como na primeira semana.

2747
02:13:49,220 --> 02:13:52,460
>O interessante parece
estar na linha 7.

2748
02:13:52,460 --> 02:13:56,870
>Scanf é uma função que recebe a entrada
do usuário, assim como get int,

2749
02:13:56,870 --> 02:13:58,500
>get string, get float e assim por diante.

2750
02:13:58,500 --> 02:14:02,630
>Mas isso só acontece quando
você precisa entender os ponteiros,

2751
02:14:02,630 --> 02:14:07,790
>porque lembre-se de nosso exemplo de swap,
se você quiser ter uma função,

2752
02:14:07,790 --> 02:14:12,110
>alterar o conteúdo de uma
variável, como fizemos com a e b

2753
02:14:12,110 --> 02:14:15,920
>e x e y, você tem que passar
o endereço da variável, cujo

2754
02:14:15,920 --> 02:14:17,060
>valor deseja alterar.

2755
02:14:17,060 --> 02:14:19,200
>Você não pode simplesmente passar o próprio x.

2756
02:14:19,200 --> 02:14:22,263
>Então, se não usássemos a
Biblioteca CS50 na primeira semana,

2757
02:14:22,263 --> 02:14:25,430
>você teria escrito código assim
apenas para obter um int do usuário.

2758
02:14:25,430 --> 02:14:27,347
>E você teria que
entender os ponteiros.

2759
02:14:27,347 --> 02:14:30,170
>E você teria que entender & e *
e assim por diante.

2760
02:14:30,170 --> 02:14:32,712
>É demais, quando tudo o que nos
preocupamos nas primeiras semanas

2761
02:14:32,712 --> 02:14:35,990
>foram loops e variáveis e condições
e tipos dos fundamentos.

2762
02:14:35,990 --> 02:14:39,230
>Mas aqui, agora temos a capacidade
de chamar a SCANF, contar

2763
02:14:39,230 --> 02:14:41,150
>para digitalizar do teclado
do usuário, por assim dizer,

2764
02:14:41,150 --> 02:14:45,380
>um inteiro ou % F nos daria
um float ou outros códigos,

2765
02:14:45,380 --> 02:14:49,040
>e passar no endereço de x para que
a SCANF possa ir a esse endereço

2766
02:14:49,040 --> 02:14:51,440
>e colocar o inteiro do
teclado do usuário.

2767
02:14:51,440 --> 02:14:53,030
>A linha 8 parece coisa da semana 1 .

2768
02:14:53,030 --> 02:14:54,680
>Eu estou apenas imprimindo o valor.

2769
02:14:54,680 --> 02:14:55,950
>E isso é bem seguro.

2770
02:14:55,950 --> 02:14:57,800
>vou continuar e fazer a SCANF.

2771
02:14:57,800 --> 02:14:58,495
>Compila ok.

2772
02:14:58,495 --> 02:14:59,870
>Vou prosseguir e executá-lo.

2773
02:14:59,870 --> 02:15:00,980
>Vou digitar 50.

2774
02:15:00,980 --> 02:15:03,180
>E pronto, ele imprime um 50.

2775
02:15:03,180 --> 02:15:06,920
>Mas há algumas estranhezas,
porque se você executar este programa também

2776
02:15:06,920 --> 02:15:09,410
>e digitar cat, então x é 0.

2777
02:15:09,410 --> 02:15:10,940
>E não há verificação de erros.

2778
02:15:10,940 --> 02:15:12,767
>Então, imediatamente,
você deve lembrar

2779
02:15:12,767 --> 02:15:14,600
>das características da
Biblioteca CS50, lembre-se,

2780
02:15:14,600 --> 02:15:17,630
>que continuamos avisando o usuário
repetidamente, se ele não estiver

2781
02:15:17,630 --> 02:15:19,310
>cooperando e dando a você um int.

2782
02:15:19,310 --> 02:15:21,740
>Esse é um recurso que
você obtém da biblioteca.

2783
02:15:21,740 --> 02:15:26,120
>Mas acontece que get string
é ainda mais poderoso,

2784
02:15:26,120 --> 02:15:29,000
>porque se eu for e mudar este programa
agora, não para obter um int,

2785
02:15:29,000 --> 02:15:30,710
>mas algo mais sofisticado como uma string -

2786
02:15:30,710 --> 02:15:33,223
>ou espere, estamos chamando de char* agora.

2787
02:15:33,223 --> 02:15:35,390
>Vou prosseguir e fazer
algo muito semelhante.

2788
02:15:35,390 --> 02:15:37,640
>Vou solicitar ao
usuário a string s.

2789
02:15:37,640 --> 02:15:39,020
>E vou usar o scanf.

2790
02:15:39,020 --> 02:15:42,320
>E vou usar % s,
assim como printf usa % s.
2791
02:15:42,320 --> 02:15:44,510
>E vou passar um s.

2792
02:15:44,510 --> 02:15:48,890
>Agora, para ficar claro, não
preciso fazer o & aqui,

2793
02:15:48,890 --> 02:15:53,010
>porque agora, todos nós sabemos que
s é fundamentalmente um endereço.

2794
02:15:53,010 --> 02:15:56,270
>Portanto, basta passar o
endereço que você já possui.

2795
02:15:56,270 --> 02:16:01,280
>Agora, vou prosseguir e imprimir os dois
pontos, a \ de % s,

2796
02:16:01,280 --> 02:16:02,930
>e imprimir s.

2797
02:16:02,930 --> 02:16:07,730
>Mas quando eu compilo isso,
make scanf, ele não gosta

2798
02:16:07,730 --> 02:16:10,970
>quando eu compilo a variável s não
inicializada quando usada aqui.

2799
02:16:10,970 --> 02:16:14,390
>Tudo bem, se eu quero
ser uma espécie de aventureiro,

2800
02:16:14,390 --> 02:16:16,350
>posso anular as proteções do make.

2801
02:16:16,350 --> 02:16:19,880
>E posso apenas compilar
manualmente usando scanf -

2802
02:16:19,880 --> 02:16:21,260
>usando clang diretamente.

2803
02:16:21,260 --> 02:16:23,600
>Isso funcionou, ./ scanf.

2804
02:16:23,600 --> 02:16:26,870
>Vamos prosseguir e
digitar, por exemplo, "HI!"

2805
02:16:26,870 --> 02:16:29,000
>e você vê estranheza, nul.

2806
02:16:29,000 --> 02:16:31,190
>Bem, felizmente,
make, e por sua vez clang,

2807
02:16:31,190 --> 02:16:33,830
>estavam nos ajudando a
ajudar a nós mesmos.

2808
02:16:33,830 --> 02:16:35,840
>Ele estava apontando que você declarou s.

2809
02:16:35,840 --> 02:16:38,660
>Você declarou
8 bytes para um ponteiro.

2810
02:16:38,660 --> 02:16:39,860
>Mas não há nada lá.

2811
02:16:39,860 --> 02:16:41,459
>É um valor de lixo.

2812
02:16:41,459 --> 02:16:43,170
>E então não há onde colocar isso.

2813
02:16:43,170 --> 02:16:45,889
>E, felizmente, printf e scanf estão
sendo inteligentes o suficiente

2814
02:16:45,889 --> 02:16:48,870
>por não apenas ir cegamente
lá e colocar H, I,

2815
02:16:48,870 --> 02:16:50,760
>ponto de exclamação em um caractere nulo.

2816
02:16:50,760 --> 02:16:52,010
>Eles estão apenas deixando para lá.
2817
02:16:52,010 --> 02:16:55,910
>E esse nul entre parênteses é um recurso
do printf que diz, você estragou tudo.

2818
02:16:55,910 --> 02:16:58,100
>Se você vir nul, significa
que fez algo errado.

2819
02:16:58,100 --> 02:17:00,830
>Está sendo generoso para evitar travar.

2820
02:17:00,830 --> 02:17:04,879
>Se eu quiser obter a entrada do
usuário, preciso ser mais esperto do que isso.

2821
02:17:04,879 --> 02:17:10,040
>E eu preciso me alocar
4 bytes, como fizemos mais cedo hoje.

2822
02:17:10,040 --> 02:17:14,209
>Ou eu poderia voltar às coisas da segunda
semana e dizer algo como, dê-me 4 bytes.

2823
02:17:14,209 --> 02:17:18,830
>Isso, porém, me dá 4 bytes
na pilha em algum lugar

2824
02:17:18,830 --> 02:17:21,410
>aqui embaixo no quadro principal, por assim dizer.

2825
02:17:21,410 --> 02:17:23,270
>Essas linhas são chamadas de quadros.

2826
02:17:23,270 --> 02:17:27,260
>Se eu usar malloc, em vez disso,
vem da chamada pilha,

2827
02:17:27,260 --> 02:17:29,780
>que não é retratada,
está mais ou menos aqui.

2828
02:17:29,780 --> 02:17:34,309
>E a única diferença é que se
estou usando o malloc, tenho que usar free.

2829
02:17:34,309 --> 02:17:38,930
>Se estou usando a pilha, como fiz na
semana dois, não preciso usar free.

2830
02:17:38,930 --> 02:17:40,730
>Gerencia-se automaticamente para mim.

2831
02:17:40,730 --> 02:17:42,590
>Francamente, há muitas
coisas novas hoje.

2832
02:17:42,590 --> 02:17:46,280
>Eu gosto da ideia de ficar com
as arrays old school.

2833
02:17:46,280 --> 02:17:51,379
>Agora, porém, se eu for em frente e fizer
make scanf, agora compilará com make.

2834
02:17:51,379 --> 02:17:55,610
>Se eu executar o scanf e digitar,
HI!, voila, parece funcionar.

2835
02:17:55,610 --> 02:17:58,549
>Mas isso é porque eu era
inteligente e previ que H-I,

2836
02:17:58,549 --> 02:17:59,660
>OK, quatro caracteres.

2837
02:17:59,660 --> 02:18:00,980
>Eu me dei 4 bytes.

2838
02:18:00,980 --> 02:18:06,110
>Mas e se o usuário digitar,
AQUI, DAVID, COMO ESTÁ?

2839
02:18:06,110 --> 02:18:08,059
>Claramente, mais de quatro bytes.

2840
02:18:08,059 --> 02:18:11,959
>E eu apertei Enter agora,
algo estranho aconteceu.

2841
02:18:11,959 --> 02:18:13,790
>O resto está perdido.
2842
02:18:13,790 --> 02:18:16,670
>E isso seria
irritante e muito frustrante

2843
02:18:16,670 --> 02:18:19,520
>se você - tentando obter a opinião do
usuário na primeira semana de aula.

2844
02:18:19,520 --> 02:18:21,500
>Get string evita isso para você.

2845
02:18:21,500 --> 02:18:23,719
>Get string chama malloc para você.

2846
02:18:23,719 --> 02:18:27,200
>E exige um pedaço de memória
tão grande quanto a string

2847
02:18:27,200 --> 02:18:28,070
>que os humanos digitam.

2848
02:18:28,070 --> 02:18:30,980
>Resumindo, nós meio que observamos
o que estão digitando

2849
02:18:30,980 --> 02:18:32,209
> caractere por caractere.

2850
02:18:32,209 --> 02:18:34,340
>E nos certificamos de
alocar ou realocar

2851
02:18:34,340 --> 02:18:38,879
>apenas memória suficiente para caber o
que quer que o humano tenha digitado.

2852
02:18:38,879 --> 02:18:42,107
>Então scanf é, uma
função como a biblioteca CS50

2853
02:18:42,107 --> 02:18:43,190
>e funciona sob o capô.

2854
02:18:43,190 --> 02:18:46,650
>Mas está fazendo tudo isso por você.
2855
02:18:46,650 --> 02:18:49,549
>E assim que você tira rodinhas
como essa, ou francamente,

2856
02:18:49,549 --> 02:18:52,469
>bibliotecas assim.

2857
02:18:52,469 --> 02:18:53,719
>Não é uma ferramenta de ensino.

2858
02:18:53,719 --> 02:18:55,070
>É uma biblioteca útil.

2859
02:18:55,070 --> 02:18:58,469
>Você mesmo precisa começar a implementar
mais dessas coisas de baixo nível.

2860
02:18:58,469 --> 02:18:59,810
>Então, novamente, há uma troca.

2861
02:18:59,810 --> 02:19:02,727
>Se você não quiser usar algo como
a biblioteca CS50, tudo bem.

2862
02:19:02,727 --> 02:19:08,400
>Agora, a responsabilidade recai sobre você para
evitar todas essas possíveis condições de erro.

2863
02:19:08,400 --> 02:19:11,209
>Tudo bem, com isso dito,
nós temos um recurso final

2864
02:19:11,209 --> 02:19:14,270
>para lhe dar a fim de motivar os
problemas desta semana, em que

2865
02:19:14,270 --> 02:19:18,230
>você explorará, manipulará e
escreverá código para alterar arquivos.

2866
02:19:18,230 --> 02:19:22,790
>E para isso, precisamos de um tópico final
de I / O de arquivo. File I/O

2867
02:19:22,790 --> 02:19:27,350
>é o termo técnico que descreve a
obtenção de entrada e saída de arquivos.

2868
02:19:27,350 --> 02:19:30,980
>Quase todos os programas que escrevemos
até agora usam apenas memória, assim

2869
02:19:30,980 --> 02:19:32,924
>aqui, por meio do qual, você
pode colocar coisas na memória.

2870
02:19:32,924 --> 02:19:34,549
>Mas assim que seu programa terminar, bum!

2871
02:19:34,549 --> 02:19:35,330
>Já se foi.

2872
02:19:35,330 --> 02:19:37,070
>O conteúdo da memória se foi.

2873
02:19:37,070 --> 02:19:39,770
>Os arquivos, é claro, estão onde
você e eu no mundo do Computação

2874
02:19:39,770 --> 02:19:42,020
>salvamos nossos artigos,
documentos e currículos

2875
02:19:42,020 --> 02:19:44,629
>e tudo isso permanentemente
no seu computador.

2876
02:19:44,629 --> 02:19:48,590
>Em C, você tem a habilidade,
certamente, para escrever você mesmo um código que

2877
02:19:48,590 --> 02:19:50,730
>salva arquivos a longo prazo.

2878
02:19:50,730 --> 02:19:53,450
>Por exemplo, vou
escrever meu próprio programa aqui,

2879
02:19:53,450 --> 02:19:59,260
>um programa de lista telefônica que
armazena nomes e números em um arquivo.

2880
02:19:59,260 --> 02:20:02,380
>Vou prosseguir e incluir,
apenas por conveniência, a biblioteca CS50

2881
02:20:02,380 --> 02:20:04,480
>de novo, porque não
quero lidar com scanf.

2882
02:20:04,480 --> 02:20:08,200
>Vou prosseguir e salvar isso,
aliás, como phonebook.c.

2883
02:20:08,200 --> 02:20:12,370
>Vou prosseguir e incluir não apenas
a biblioteca CS50, mas o io padrão.

2884
02:20:12,370 --> 02:20:18,373
>E preventivamente, irei prosseguir
e incluir string.h também.

2885
02:20:18,373 --> 02:20:20,290
>E vou prosseguir na
minha função main.

2886
02:20:20,290 --> 02:20:23,990
>E vou usar algumas novas funções
que veremos brevemente aqui.

2887
02:20:23,990 --> 02:20:27,260
>Mas no próximo conjunto de problemas,
você os explorará com mais detalhes.

2888
02:20:27,260 --> 02:20:29,980
>Vou criar uma indicação
para um arquivo.

2889
02:20:29,980 --> 02:20:33,820
>Acontece que, estranhamente,
que em maiúsculas, FILE,

2890
02:20:33,820 --> 02:20:38,540
>este é um novo tipo de dados que vem
com C que representa um arquivo.

2891
02:20:38,540 --> 02:20:42,383
>Vou seguir em frente e criar
uma indicação para um arquivo,
2892
02:20:42,383 --> 02:20:43,300
>o endereço de um arquivo.

2893
02:20:43,300 --> 02:20:44,800
>E vou chamar o arquivo variável.

2894
02:20:44,800 --> 02:20:46,300
>Eu poderia chamar f, poderia chamar de x.

2895
02:20:46,300 --> 02:20:49,130
>Vou chamar de arquivo em letras
minúsculas, só para ficar claro.

2896
02:20:49,130 --> 02:20:52,180
>E vou usar uma nova função chamada f
open, que significa abrir arquivo.

2897
02:20:52,180 --> 02:20:54,077
>E a abertura do arquivo leva dois argumentos.

2898
02:20:54,077 --> 02:20:57,160
>Recebe o primeiro argumento, que é o nome
de um arquivo que deseja abrir.

2899
02:20:57,160 --> 02:20:59,638
>Vou abrir um arquivo
chamado phonebook.csv.

2900
02:20:59,638 --> 02:21:02,680
>E então vou prosseguir e abri-lo,
especificamente, no modo anexar.

2901
02:21:02,680 --> 02:21:05,050
>Resumindo, você pode abrir
arquivos de diferentes maneiras,

2902
02:21:05,050 --> 02:21:08,450
>lê-los, isto é, basta olhar para
o seu conteúdo, escrevê-los,

2903
02:21:08,450 --> 02:21:10,780
>que é mudar seu
conteúdo completamente,

2904
02:21:10,780 --> 02:21:15,730
>ou para anexar a eles, a, que significa
adicionar linha por linha a eles,

2905
02:21:15,730 --> 02:21:18,370
>para continuar a fornecer
mais informações.

2906
02:21:18,370 --> 02:21:20,210
>Vou continuar e,
só para ficar seguro,

2907
02:21:20,210 --> 02:21:23,650
>vou dizer que se o
arquivo é igual a nul,

2908
02:21:23,650 --> 02:21:26,180
>porque lembre-se de que nul
significa que algo deu errado,

2909
02:21:26,180 --> 02:21:27,280
>vamos retornar agora.

2910
02:21:27,280 --> 02:21:28,960
>Talvez eu tenha digitado incorretamente o nome do arquivo.

2911
02:21:28,960 --> 02:21:29,950
>Talvez não exista.

2912
02:21:29,950 --> 02:21:31,420
>Algo deu errado, provavelmente.

2913
02:21:31,420 --> 02:21:34,660
>Vou verificar isso dizendo:
se o arquivo for igual a nul, apenas

2914
02:21:34,660 --> 02:21:36,178
>saia do programa agora.

2915
02:21:36,178 --> 02:21:38,470
>Mas depois disso, vou prosseguir
e obter uma string.

2916
02:21:38,470 --> 02:21:41,920
>Mas podemos chamar de char*
agora, chamada de name.

2917
02:21:41,920 --> 02:21:44,440
>E vou pedir um
nome ao usuário.

2918
02:21:44,440 --> 02:21:45,820
>E já fizemos isso antes.

2919
02:21:45,820 --> 02:21:48,610
>Vou pedir a eles um número,
um número de telefone.

2920
02:21:48,610 --> 02:21:49,970
>E já fizemos isso antes.

2921
02:21:49,970 --> 02:21:52,690
>A única diferença, agora, é
estou chamando string char*.

2922
02:21:52,690 --> 02:21:54,400
>E agora, aqui está a parte legal.

2923
02:21:54,400 --> 02:21:56,830
>Acontece que, se eu quiser
salvar este nome e número

2924
02:21:56,830 --> 02:21:58,990
>a esse arquivo permanentemente em um CSV -

2925
02:21:58,990 --> 02:22:02,170
>se desconhecido, popular no mundo
da consultoria, o mundo analítico.

2926
02:22:02,170 --> 02:22:04,900
>É apenas uma planilha,
um valor separado por vírgula

2927
02:22:04,900 --> 02:22:08,470
>arquivo que você pode abrir no Excel
ou planilha do Google.

2928
02:22:08,470 --> 02:22:13,660
>Vou prosseguir e, não printf,
mas fprintf para esse arquivo,

2929
02:22:13,660 --> 02:22:18,580
>uma string seguida por uma vírgula, seguida
por uma string, seguida por uma nova linha,
2930
02:22:18,580 --> 02:22:21,070
>conectando o nome e o número.

2931
02:22:21,070 --> 02:22:25,280
>E então, aqui embaixo,
fecharei o arquivo.

2932
02:22:25,280 --> 02:22:28,570
>Então, isso é novo. fprintf não
é printf, que imprime na tela.

2933
02:22:28,570 --> 02:22:30,307
>fprintf imprime em um arquivo.

2934
02:22:30,307 --> 02:22:32,890
>Então você tem que passar mais
um argumento, o primeiro, que

2935
02:22:32,890 --> 02:22:37,150
>é o ponteiro para o arquivo para o qual
é deseja enviar essas novas strings.

2936
02:22:37,150 --> 02:22:40,180
>Então você ainda fornece uma string
de formato, que diz, hey fprintf,

2937
02:22:40,180 --> 02:22:43,060
>este é o tipo de dados que
desejo imprimir no arquivo.

2938
02:22:43,060 --> 02:22:46,930
>E então você conecta as variáveis,
assim como sempre fizemos com printf.

2939
02:22:46,930 --> 02:22:49,610
>E, por último, fechamos o arquivo.

2940
02:22:49,610 --> 02:22:53,200
>Resumindo, este programa parece solicitar
a um humano um nome e um número.

2941
02:22:53,200 --> 02:22:55,420
>E então vai seguir em frente
e escrever esses nomes

2942
02:22:55,420 --> 02:22:56,990
>e números para o arquivo.

2943
02:22:56,990 --> 02:22:59,035
>Então agora eu vou fazer a lista telefônica.

2944
02:22:59,035 --> 02:23:07,810
>OK, nenhum erro até agora, lista
telefônica ./, David, 949-468-2750.

2945
02:23:07,810 --> 02:23:11,140
>OK, deixe-me executá-lo mais uma vez,
embora nada pareça ter acontecido.

2946
02:23:11,140 --> 02:23:15,730
>Brian, que tal 617-495-1000, Enter.

2947
02:23:15,730 --> 02:23:17,950
>Vamos verificar meu explorador de arquivos aqui.

2948
02:23:17,950 --> 02:23:22,240
>Observe, todos os arquivos que criamos
hoje, incluindo, se eu aumentar o zoom,

2949
02:23:22,240 --> 02:23:25,390
>não apenas phonebook.c, mas phonebook.csv.

2950
02:23:25,390 --> 02:23:29,290
>E se eu clicar duas vezes nisso,
observe o que está dentro disso.

2951
02:23:29,290 --> 02:23:33,700
>Voila, o nome de David, o nome de
Brian e cada um dos nossos números.

2952
02:23:33,700 --> 02:23:36,280
>E ainda mais legal do que isso,
agora eu vou encerrar isso.

2953
02:23:36,280 --> 02:23:40,213
>Vamos prosseguir e baixar
este arquivo usando o IDE.

2954
02:23:40,213 --> 02:23:42,380
>E isso vai colocá-lo na
minha pasta Downloads.

2955
02:23:42,380 --> 02:23:43,420
>Eu vou clicar nele.

2956
02:23:43,420 --> 02:23:45,545
>E vai abrir
Excel ou Numbers ou qualquer outra coisa

2957
02:23:45,545 --> 02:23:47,470
>que você tem no seu Mac ou PC.

2958
02:23:47,470 --> 02:23:50,740
>Vou prosseguir.

2959
02:23:50,740 --> 02:23:54,400
>E voila, parece um pouco
estúpido nesta formatação aqui.

2960
02:23:54,400 --> 02:23:57,160
>Mas eu abri uma planilha
que eu mesmo gerei

2961
02:23:57,160 --> 02:24:01,390
>usando fopen, fprintf e fclose.

2962
02:24:01,390 --> 02:24:04,180
>Então, agora que temos
ponteiros à nossa disposição,

2963
02:24:04,180 --> 02:24:08,292
>podemos manipular coisas
como arquivos, o que é muito legal.

2964
02:24:08,292 --> 02:24:10,000
>Mas vamos fazer isso
esta semana, não

2965
02:24:10,000 --> 02:24:12,940
>com texto, mas com tipos
específicos reais de arquivos.

2966
02:24:12,940 --> 02:24:16,840
>E, lembre-se desse
tipo de pensamento aqui.

2967
02:24:16,840 --> 02:24:19,150
>Se você olhar para isso,
provavelmente é muito enigmático.
2968
02:24:19,150 --> 02:24:21,400
>Parece um código de
máquina, mas não é.

2969
02:24:21,400 --> 02:24:24,070
>Esta é, talvez, a
representação mais simples

2970
02:24:24,070 --> 02:24:26,410
>de um rosto sorridente dentro de um arquivo.

2971
02:24:26,410 --> 02:24:31,000
>Se você tiver um arquivo de bitmap, um mapa
de bits, uma grade de bits, esses bits,

2972
02:24:31,000 --> 02:24:33,130
>muito simplesmente, podem ser
literalmente 0's e 1's.

2973
02:24:33,130 --> 02:24:37,240
>E se você atribuir a cor preta
a 0 e a cor branca a 1,

2974
02:24:37,240 --> 02:24:40,660
>você poderia pensar nesta
mesma grade de 0 e 1 representando,

2975
02:24:40,660 --> 02:24:41,930
>na verdade, um rosto sorridente.

2976
02:24:41,930 --> 02:24:43,690
>Em outras palavras, aqui estão alguns pixels.

2977
02:24:43,690 --> 02:24:45,520
>Falamos sobre pixels na semana zero.

2978
02:24:45,520 --> 02:24:49,567
>Pixels são apenas os pontos que compõem
um arquivo gráfico em seu computador.

2979
02:24:49,567 --> 02:24:50,650
>E os pixels estão por toda parte.

2980
02:24:50,650 --> 02:24:53,320
>Todos nós, agora, sintonizando ao vivo
via Zoom ou YouTube ou similares,

2981
02:24:53,320 --> 02:24:56,800
>estamos assistindo a fluxos de pixels,
que compõem várias imagens e várias

2982
02:24:56,800 --> 02:25:02,290
>imagens compondo vídeos que parecem
estar se movendo em 20 ou 30

2983
02:25:02,290 --> 02:25:04,670
>quadros por segundo.

2984
02:25:04,670 --> 02:25:08,530
>Agora, é claro, há um limite de
fidelidade nesse tipo de imagem.

2985
02:25:08,530 --> 02:25:11,097
>E é bastante comum no
caso da TV e do cinema,

2986
02:25:11,097 --> 02:25:13,930
>se houver algum bandido que foi
pego em alguma gravação de vigilância,

2987
02:25:13,930 --> 02:25:17,050
>ou similares, invariavelmente,
o staff do Direito

2988
02:25:17,050 --> 02:25:19,930
>pode melhorar o vídeo e aumentar, para ver

2989
02:25:19,930 --> 02:25:24,710
>exatamente a pessoa
que cometeu tal crime.

2990
02:25:24,710 --> 02:25:26,140
>Bem, isso tudo é um absurdo.

2991
02:25:26,140 --> 02:25:29,367
>E deriva de alguns dos primitivos
que introduzimos na semana zero.

2992
02:25:29,367 --> 02:25:31,450
>Na verdade, só para brincar com
isso, deixe-me ir em frente
2993
02:25:31,450 --> 02:25:34,990
>e passar alguns segundos desse
programa de TV aqui nos EUA

2994
02:25:34,990 --> 02:25:39,670
>chamado CSI, apenas para lhe dar uma
noção de quão comum esse tipo de lógica

2995
02:25:39,670 --> 02:25:40,180
>é.

2996
02:25:40,180 --> 02:25:41,140
>[REPRODUÇÃO DE VÍDEO]

2997
02:25:41,140 --> 02:25:43,330
>- Nós sabemos.

2998
02:25:43,330 --> 02:25:46,930
>- Isso às 9:15, Ray
Santoya estava no caixa eletrônico.

2999
02:25:46,930 --> 02:25:50,380
>- Então a questão é,
o que ele estava fazendo às 9:16?

3000
02:25:50,380 --> 02:25:53,180
>- Atirando com sua 9 milímetros
em alguma coisa.

3001
02:25:53,180 --> 02:25:54,820
>Talvez ele tenha visto o atirador.

3002
02:25:54,820 --> 02:25:56,920
>- Ou estava trabalhando com ele.

3003
02:25:56,920 --> 02:25:59,490
>- Espere, volte um.

3004
02:25:59,490 --> 02:26:00,481
>- O que você vê?

3005
02:26:00,481 --> 02:26:05,291
>[CLICANDO]

3006
02:26:07,700 --> 02:26:11,420
>- Traga o rosto para cima, tela inteira.

3007
02:26:11,420 --> 02:26:12,530
>- Os óculos dele.

3008
02:26:12,530 --> 02:26:13,982
>- Há um reflexo.

3009
02:26:13,982 --> 02:26:17,426
>[DIGITANDO]

3010
02:26:23,840 --> 02:26:25,620
>- Esse é o time de beisebol, Neuvitas.

3011
02:26:25,620 --> 02:26:26,630
>Esse é o logotipo deles.

3012
02:26:26,630 --> 02:26:29,075
>- E está falando com quem
está vestindo essa jaqueta.

3013
02:26:29,075 --> 02:26:31,160
>- Podemos ter uma testemunha.

3014
02:26:31,160 --> 02:26:32,700
>- Para ambos os tiroteios.

3015
02:26:32,700 --> 02:26:33,283
>[FIM DA REPRODUÇÃO]

3016
02:26:33,283 --> 02:26:36,408
>DAVID MALAN: Então, infelizmente,
hoje vamos estragar muitos filmes e séries

3017
02:26:36,408 --> 02:26:38,650
>para você, porque você não pode
simplesmente aumentar o zoom infinitamente

3018
02:26:38,650 --> 02:26:41,250
>e ver mais informações se essas
informações não estiverem lá.

3019
02:26:41,250 --> 02:26:43,750
>no fim das contas, há apenas
um número finito de bits.
3020
02:26:43,750 --> 02:26:46,120
>E, caso em questão, aqui está
uma fotografia de Brian.

3021
02:26:46,120 --> 02:26:48,580
>E você pode ver que,
há um brilho em seus olhos.

3022
02:26:48,580 --> 02:26:50,930
>Vamos ver o que estava
refletido no olho dele ali.

3023
02:26:50,930 --> 02:26:53,410
>E se dermos um zoom
nesta imagem de Brian,

3024
02:26:53,410 --> 02:26:57,730
>e talvez possamos ampliar um pouco mais,
isso é tudo o que existe.

3025
02:26:57,730 --> 02:27:00,160
>Você não pode simplesmente clicar
no botão aprimorar e ver mais,

3026
02:27:00,160 --> 02:27:02,368
>porque no fim das contas,
são apenas pixels.

3027
02:27:02,368 --> 02:27:06,310
>E pixels, como visto na semana zero, são apenas
0's e 1's, finitamente.

3028
02:27:06,310 --> 02:27:08,470
>Então, o que você vê é o que você obtém.

3029
02:27:08,470 --> 02:27:12,190
>Agora, com isso dito - e na verdade,
podemos zombar disso também, aqui.

3030
02:27:12,190 --> 02:27:14,830
>Vamos reproduzir um outro
clipe curto de Futurama,

3031
02:27:14,830 --> 02:27:18,423
>que mostra esse ponto também,
mas de forma mais divertida.
3032
02:27:18,423 --> 02:27:19,090
>[REPRODUÇÃO DE VÍDEO]

3033
02:27:19,090 --> 02:27:23,250
>- Aumente a velocidade da morte.

3034
02:27:23,250 --> 02:27:24,770
>Por que ainda está borrado?

3035
02:27:24,770 --> 02:27:26,710
>- Essa é toda a resolução que temos.

3036
02:27:26,710 --> 02:27:29,050
>Aumentar o zoom não o
torna mais claro.

3037
02:27:29,050 --> 02:27:31,220
>- Fazem isso no CSI: Miami.

3038
02:27:31,220 --> 02:27:32,020
>- [SUSPIRAR]

3039
02:27:32,020 --> 02:27:32,170
>[FIM DA REPRODUÇÃO]

3040
02:27:32,170 --> 02:27:35,212
>DAVID MALAN: Então, temos dois clipes
conversando, na verdade, um com o outro.

3041
02:27:35,212 --> 02:27:37,330
>Mas tenho que atualizar as coisas para 2020.

3042
02:27:37,330 --> 02:27:41,972
>Você não pode pegar a internet
hoje em dia ou a revista hoje em dia,

3043
02:27:41,972 --> 02:27:43,930
>que de alguma forma não mencione

3044
02:27:43,930 --> 02:27:45,850
>aprendizado de máquina e
inteligência artificial

3045
02:27:45,850 --> 02:27:48,005
>e algoritmos sofisticados por meio
dos quais você pode fazer coisas

3046
02:27:48,005 --> 02:27:49,630
>que anteriormente não era possível.

3047
02:27:49,630 --> 02:27:51,460
>E isso é meio
que o caso.

3048
02:27:51,460 --> 02:27:56,290
>Você deve se lembrar da semana zero,
que encontramos esta bela aquarela

3049
02:27:56,290 --> 02:28:00,250
>de pintura nos arquivos de Harvard que tem
apenas cerca de 11 polegadas de altura total.

3050
02:28:00,250 --> 02:28:03,700
>E ainda assim, de alguma forma, tem
13 pés de altura aqui atrás de mim.

3051
02:28:03,700 --> 02:28:06,533
>Agora, normalmente, se você fosse apenas
realçar esta pintura em aquarela,

3052
02:28:06,533 --> 02:28:08,658
>começaria a parecer muito
estúpido muito rapidamente

3053
02:28:08,658 --> 02:28:10,570
>com muita e muita
pixelização, mesmo se você

3054
02:28:10,570 --> 02:28:12,940
>usar uma câmera muito sofisticada,
como costumam fazer,

3055
02:28:12,940 --> 02:28:14,440
>para capturar a imagem original.

3056
02:28:14,440 --> 02:28:16,810
>Mas queríamos aumentar
para 4 metros de altura

3057
02:28:16,810 --> 02:28:21,110
>para que ficasse em alta
qualidade o tempo todo.
3058
02:28:21,110 --> 02:28:24,790
>E aí, usamos o
aprimoramento, de certa forma.

3059
02:28:24,790 --> 02:28:28,640
>Então, usando, para encurtar a longa história, algoritmos
mais sofisticados do que os da semana passada,

3060
02:28:28,640 --> 02:28:31,690
>você pode usar inteligência
artificial, aprendizado de máquina,

3061
02:28:31,690 --> 02:28:36,130
>para analisar os dados e
encontrar padrões onde não havia -

3062
02:28:36,130 --> 02:28:38,280
>que não são necessariamente
visíveis ao olho humano.

3063
02:28:38,280 --> 02:28:41,590
>Por exemplo, se pegarmos o original
aqui e começarmos a aumentar o zoom,

3064
02:28:41,590 --> 02:28:43,600
>parece muito bom nesta resolução.

3065
02:28:43,600 --> 02:28:44,720
>Mas é muito bom.

3066
02:28:44,720 --> 02:28:48,730
>Você não vê o fato de que
isso era tinta em uma tela real.

3067
02:28:48,730 --> 02:28:50,707
>Então, isso foi apenas
um zoom no Photoshop.

3068
02:28:50,707 --> 02:28:52,540
>Mas quando você
executa uma imagem como esta

3069
02:28:52,540 --> 02:28:55,990
>por meio de software sofisticado baseado em
aprendizado de máquina, inteligência artificial,
3070
02:28:55,990 --> 02:28:58,570
>você pode começar a
melhorá-la e ver,

3071
02:28:58,570 --> 02:29:01,390
>não apenas esta janela do
topo de um dos edifícios, que

3072
02:29:01,390 --> 02:29:03,520
>é bem borrado
aqui no Photoshop,

3073
02:29:03,520 --> 02:29:05,480
>mas você pode começar a ver mais detalhes.

3074
02:29:05,480 --> 02:29:08,750
>Então, isso é literalmente o antes,
apenas ampliando no Photoshop.

3075
02:29:08,750 --> 02:29:12,572
>Isso é depois de aplicar algoritmos
sofisticados de inteligência artificial

3076
02:29:12,572 --> 02:29:15,280
>que vemos, espere um minuto,
há uma pequena descoloração ali.

3077
02:29:15,280 --> 02:29:17,072
>Espere, há um pouco
de descoloração aí.

3078
02:29:17,072 --> 02:29:20,830
>E hoje em dia, o aprimoramento está
cada vez mais se tornando uma realidade.

3079
02:29:20,830 --> 02:29:22,450
>Ainda está melhorando.

3080
02:29:22,450 --> 02:29:25,270
>Não é ressuscitar informações
que necessariamente existiam.

3081
02:29:25,270 --> 02:29:28,240
>Mas sim acertar mais, algoritmicamente,

3082
02:29:28,240 --> 02:29:30,487
>para reconstruir o que a
imagem era.

3083
02:29:30,487 --> 02:29:32,320
>E se ampliarmos ainda
mais, você pode, talvez,

3084
02:29:32,320 --> 02:29:35,440
>ver que isso está começando a ficar
borrado se você usar apenas o Photoshop

3085
02:29:35,440 --> 02:29:36,578
>e continuar ampliando.

3086
02:29:36,578 --> 02:29:38,620
>Mas se você executar por meio de
algoritmos sofisticados o suficiente

3087
02:29:38,620 --> 02:29:40,780
>e começar a notar pequenas
descolorações que

3088
02:29:40,780 --> 02:29:44,920
>não são super visíveis para o olho
humano, podemos melhorar ainda mais.

3089
02:29:44,920 --> 02:29:46,540
>E você não pode fazer isso infinitamente.

3090
02:29:46,540 --> 02:29:48,550
>E, de certa forma, estamos
criando informações

3091
02:29:48,550 --> 02:29:51,282
>onde não há necessariamente
essa informação lá.

3092
02:29:51,282 --> 02:29:54,490
>Então, se esses tipos de coisas se
mantêm no tribunal é outra questão.

3093
02:29:54,490 --> 02:29:56,920
>Mas pode melhorar a fidelidade
de imagens como esta.

3094
02:29:56,920 --> 02:30:02,570
>E, isso nos permitiu
ampliar de 11 polegadas a 13 pés.

3095
02:30:02,570 --> 02:30:05,920
>Então, quando se trata de manipular
imagens, em última análise, nós

3096
02:30:05,920 --> 02:30:10,030
>temos algumas capacidades programáticas,
incluindo este ponteiro de arquivo,

3097
02:30:10,030 --> 02:30:13,280
>como acabamos de ver, e também,
algumas outras funções.

3098
02:30:13,280 --> 02:30:15,550
>E nossos exemplos finais,
aqui, vão colocar a fundação

3099
02:30:15,550 --> 02:30:17,380
>pelo que você fará
esta semana, que

3100
02:30:17,380 --> 02:30:21,250
>é manipular seus próprios arquivos
gráficos com um novo entendimento

3101
02:30:21,250 --> 02:30:25,270
>de ponteiros e endereços e agora
arquivos e entrada e saída.

3102
02:30:25,270 --> 02:30:30,010
>Por exemplo, vou prosseguir e
abrir um programa aqui chamado -

3103
02:30:30,010 --> 02:30:32,110
>me dê apenas um segundo.

3104
02:30:32,110 --> 02:30:37,660
>Vou abrir um programa
aqui chamado jpeg.c.

3105
02:30:37,660 --> 02:30:40,610
>E este programa, jpeg.c,
que escrevi antes,

3106
02:30:40,610 --> 02:30:43,400
>que está no site do
curso, faz o seguinte.

3107
02:30:43,400 --> 02:30:46,510
>Primeiro, ele declara um tipo chamado byte.

3108
02:30:46,510 --> 02:30:49,990
>Acontece que, em C, não há uma
definição comum do que é um byte.

3109
02:30:49,990 --> 02:30:51,610
>Um bite, como conhecemos, é um pedaço.

3110
02:30:51,610 --> 02:30:53,680
>E acontece que a maneira
mais simples de criar

3111
02:30:53,680 --> 02:30:57,250
>um byte é definir o nosso pedaço,
assim como definimos uma string,

3112
02:30:57,250 --> 02:31:01,840
>assim como definimos outros tipos
também, como um estudante, a fim -

3113
02:31:01,840 --> 02:31:04,640
>de que uma pessoa possa
nos fornecer um byte.

3114
02:31:04,640 --> 02:31:07,210
>Portanto, esta primeira linha de
código apenas declara um tipo de dados

3115
02:31:07,210 --> 02:31:11,830
>chamado byte, usando outro tipo de dados mais
misterioso chamado u int a sublinhado t.

3116
02:31:11,830 --> 02:31:13,330
>Mas mais disso no conjunto de problemas.

3117
02:31:13,330 --> 02:31:15,820
>Acabamos de inventar
algo chamado byte.

3118
02:31:15,820 --> 02:31:17,928
>Observe, neste programa,
estou ressuscitando a ideia
3119
02:31:17,928 --> 02:31:21,220
>da segunda semana de argumentos de linha de comando,
onde podemos obter a entrada do usuário.

3120
02:31:21,220 --> 02:31:23,860
>Observe que estou verificando se o
usuário digitou dois argumentos.

3121
02:31:23,860 --> 02:31:27,520
>E s não, estou devolvendo um
imediatamente para significar erro.

3122
02:31:27,520 --> 02:31:30,490
>Na linha 17, estou usando minha nova técnica.

3123
02:31:30,490 --> 02:31:34,210
>Estou abrindo um arquivo
usando o nome do arquivo

3124
02:31:34,210 --> 02:31:36,050
>que o humano digitou
na linha de comando.

3125
02:31:36,050 --> 02:31:40,270
>E, desta vez, estou abrindo para ler
"r" em vez de a.

3126
02:31:40,270 --> 02:31:41,660
>Mas se não houver um arquivo -

3127
02:31:41,660 --> 02:31:44,920
>então, se o arquivo bang, isto é,
se arquivo de ponto de exclamação,

3128
02:31:44,920 --> 02:31:47,990
>ou se o arquivo for igual a NULL,
significam a mesma coisa.

3129
02:31:47,990 --> 02:31:51,040
>Posso prosseguir e devolver
um, significando um erro.

3130
02:31:51,040 --> 02:31:53,710
>Aqui embaixo, estou fazendo
algo um pouco inteligente.

3131
02:31:53,710 --> 02:31:56,890
>Acontece que com uma
probabilidade muito alta,

3132
02:31:56,890 --> 02:32:01,640
>você pode determinar se algum arquivo é um
jpeg olhando apenas para os três primeiros

3133
02:32:01,640 --> 02:32:02,140
>bytes.

3134
02:32:02,140 --> 02:32:04,720
>Muitos formatos de arquivo têm o
que chamamos de números mágicos

3135
02:32:04,720 --> 02:32:06,350
>no início de seus arquivos.

3136
02:32:06,350 --> 02:32:10,990
>E esses são números padrão da
indústria, 1 ou 2 ou 3 ou mais deles,

3137
02:32:10,990 --> 02:32:13,910
>que normalmente se espera que
esteja no início de um arquivo,

3138
02:32:13,910 --> 02:32:16,240
>para que um programa possa verificar
rapidamente, isso é um jpeg?

3139
02:32:16,240 --> 02:32:16,960
>Isso é um GIF?

3140
02:32:16,960 --> 02:32:18,070
>Este é um documento do Word?

3141
02:32:18,070 --> 02:32:19,300
>Este é um arquivo Excel?

3142
02:32:19,300 --> 02:32:21,910
>Eles tendem a ter esses
números no início deles.

3143
02:32:21,910 --> 02:32:26,020
>E os JPEGs têm uma sequência de
bytes que estamos prestes a ver.
3144
02:32:26,020 --> 02:32:29,770
>Esta linha de código 24 aqui, como você
verá no próximo conjunto de problemas,

3145
02:32:29,770 --> 02:32:33,070
>é como você pode dar a si mesmo um
buffer de bytes, especificamente

3146
02:32:33,070 --> 02:32:35,320
>um array de três bytes.

3147
02:32:35,320 --> 02:32:38,380
>A próxima linha de código, como você verá
na próxima semana, é chamada de fread.

3148
02:32:38,380 --> 02:32:40,720
>fread, como o nome
sugere, lê um arquivo.

3149
02:32:40,720 --> 02:32:42,940
>Ou seja, ele pega bytes de um arquivo.

3150
02:32:42,940 --> 02:32:45,790
>E é um pouco sofisticado de usar,
mas você ficará mais confortável

3151
02:32:45,790 --> 02:32:47,140
>com isso ao longo do tempo.

3152
02:32:47,140 --> 02:32:52,060
>Ele lê neste buffer, seu primeiro
argumento, o tamanho deste tipo de dados,

3153
02:32:52,060 --> 02:32:53,050
>o tamanho de um byte.

3154
02:32:53,050 --> 02:32:58,250
>E ele lê muitos desses tipos
de dados deste arquivo.

3155
02:32:58,250 --> 02:33:01,480
>Então, novamente, é para argumentos,
o que é muito pelo que vimos.

3156
02:33:01,480 --> 02:33:08,230
>Mas ele lê a partir deste arquivo,
três bytes nesse array,

3157
02:33:08,230 --> 02:33:09,770
>buffer também conhecido como, denominado bytes.

3158
02:33:09,770 --> 02:33:13,460
>Então é assim que você escreve código
que não coloca dados em um arquivo,

3159
02:33:13,460 --> 02:33:14,650
>mas lê a partir dele.

3160
02:33:14,650 --> 02:33:16,700
>E então aqui, observe nosso hexadecimal.

3161
02:33:16,700 --> 02:33:18,190
>Então, fechamos o círculo.

3162
02:33:18,190 --> 02:33:23,110
>Se bytes, colchete 0 é
igual a 0xff e bytes

3163
02:33:23,110 --> 02:33:27,080
>colchete 1 é igual a 0xd8 e bytes
colchete 2 é igual a 0xff,

3164
02:33:27,080 --> 02:33:28,960
>isso definitivamente parece enigmático para você.

3165
02:33:28,960 --> 02:33:31,570
>Mas isso é só porque eu
procurei no manual de jpegs,

3166
02:33:31,570 --> 02:33:34,900
>e acontece que quase
qualquer JPEG, ao contrário,

3167
02:33:34,900 --> 02:33:39,430
>deve começar com 0xff, 0xd8, 0xff.

3168
02:33:39,430 --> 02:33:43,450
>Esses são os primeiros três bytes de
qualquer jpeg em seu Mac, seu PC,

3169
02:33:43,450 --> 02:33:44,350
>na internet.
3170
02:33:44,350 --> 02:33:46,300
>Sempre existem esses três bytes.

3171
02:33:46,300 --> 02:33:50,500
>Acontece que o quarto byte
ainda decide se

3172
02:33:50,500 --> 02:33:51,730
>um arquivo é, na verdade, um jpeg.

3173
02:33:51,730 --> 02:33:54,640
>Mas o algoritmo para isso é um pouco
mais elaborado, então mantive-o simples.

3174
02:33:54,640 --> 02:33:59,020
>Se os primeiros três bytes de um arquivo
forem esses, talvez você tem um jpeg.

3175
02:33:59,020 --> 02:34:01,150
>Mas se você não tiver
exatamente esses três bytes,

3176
02:34:01,150 --> 02:34:02,920
>você definitivamente não tem um JPEG.

3177
02:34:02,920 --> 02:34:05,270
>E então o que posso fazer,
aqui, é o seguinte.

3178
02:34:05,270 --> 02:34:09,700
>No código de hoje - deixe-me prosseguir
e pegar dois outros arquivos

3179
02:34:09,700 --> 02:34:11,620
>que eu trouxe comigo.

3180
02:34:11,620 --> 02:34:16,210
>E acontece que é uma
fotografia novamente.

3181
02:34:16,210 --> 02:34:18,160
>Dê-me um segundo.

3182
02:34:18,160 --> 02:34:24,010
>Eu trouxe comigo alguns arquivos,
um dos quais é chamado brian.jpeg,

3183
02:34:24,010 --> 02:34:25,870
>que é a mesma foto de Brian.

3184
02:34:25,870 --> 02:34:28,030
>E então eu tenho um gif,
o que é claro, não é

3185
02:34:28,030 --> 02:34:31,210
>um jpeg, que é esse gato digitando aqui.

3186
02:34:31,210 --> 02:34:33,250
>E o que eu, efetivamente,
tem na minha frente agora

3187
02:34:33,250 --> 02:34:37,870
>é um programa que, se eu fizer make jpeg,
porque este arquivo é jpeg.c,

3188
02:34:37,870 --> 02:34:43,360
>e executo o ./ jpeg,
posso digitar algo como cat.gif

3189
02:34:43,360 --> 02:34:46,990
>na linha de comando como um argumento,
Enter, e eu não verei nenhum.

3190
02:34:46,990 --> 02:34:51,550
>Por outro lado, se eu passar o JPEG de Brian
na linha de comando como um argumento,

3191
02:34:51,550 --> 02:34:52,630
>Eu vejo talvez.

3192
02:34:52,630 --> 02:34:54,430
>E novamente, talvez
apenas porque o algoritmo

3193
02:34:54,430 --> 02:34:56,638
>para julgar
se algo é um JPEG

3194
02:34:56,638 --> 02:34:58,550
>é um pouco mais complicado do que isso.

3195
02:34:58,550 --> 02:35:02,590
>Mas, agora posso acessar os bytes
individuais e, portanto, os pixels,

3196
02:35:02,590 --> 02:35:06,310
>ao que parece, de um arquivo de imagem.

3197
02:35:06,310 --> 02:35:08,575
>E, podemos até fazer isso.

3198
02:35:08,575 --> 02:35:10,450
>Eu vou
mostrar um último programa

3199
02:35:10,450 --> 02:35:13,960
>que escrevemos deliberadamente antes,
apenas para lhe dar um gostinho do que está

3200
02:35:13,960 --> 02:35:15,790
>vindo com o próximo conjunto de problemas.

3201
02:35:15,790 --> 02:35:19,480
>Este programa é uma reimplementação
do programa que você provavelmente

3202
02:35:19,480 --> 02:35:21,820
>deve ter usado uma ou mais vezes chamado de CP.

3203
02:35:21,820 --> 02:35:25,570
>Lembre-se de que o CP é um
programa no IDE e no Linux,

3204
02:35:25,570 --> 02:35:27,730
>de forma mais geral, isso permite
que você copie um arquivo.

3205
02:35:27,730 --> 02:35:31,660
>Você faz CP, espaço, nome do arquivo,
espaço, o novo nome de arquivo.

3206
02:35:31,660 --> 02:35:32,650
>Como é que isso funciona?

3207
02:35:32,650 --> 02:35:37,090
>Agora tenho todos os blocos de construção
com os quais posso copiar arquivos sozinho.
3208
02:35:37,090 --> 02:35:39,100
>Então, novamente, estou definindo um byte aqui.

3209
02:35:39,100 --> 02:35:41,930
>Estou definindo main como aceitando
argumentos de linha de comando aqui.

3210
02:35:41,930 --> 02:35:43,000
>E observe uma mudança.

3211
02:35:43,000 --> 02:35:44,800
>Não estou usando a biblioteca CS50.

3212
02:35:44,800 --> 02:35:52,090
>Então, mesmo o que antes era string
na semana dois agora é char*.

3213
02:35:52,090 --> 02:35:55,450
>Mesmo aqui para argv, estou
garantindo que os tipos humanos

3214
02:35:55,450 --> 02:36:00,580
>em três palavras, o nome do programa
e o arquivo de origem e o arquivo

3215
02:36:00,580 --> 02:36:01,180
>de destino.

3216
02:36:01,180 --> 02:36:02,410
>Estou usando o fopen novamente.

3217
02:36:02,410 --> 02:36:06,100
>Estou abrindo o arquivo
de origem aqui do argv1.

3218
02:36:06,100 --> 02:36:07,358
>Estou garantindo que não seja nulo.

3219
02:36:07,358 --> 02:36:08,650
>E então estou desistindo, se for.

3220
02:36:08,650 --> 02:36:13,030
>Eu estou então - aqui está algo novo,
abrindo o arquivo de destino aqui, também

3221
02:36:13,030 --> 02:36:13,870
>com fopen.

3222
02:36:13,870 --> 02:36:15,700
>Mas estou usando "w."

3223
02:36:15,700 --> 02:36:19,630
>Estou abrindo um arquivo com r, um
arquivo para w, porque quero ler de um

3224
02:36:19,630 --> 02:36:21,160
>e escrever para o outro.

3225
02:36:21,160 --> 02:36:25,360
>E aqui embaixo, este loop
é uma maneira inteligente

3226
02:36:25,360 --> 02:36:27,370
>de copiar um arquivo para outro.

3227
02:36:27,370 --> 02:36:30,790
>Estou me dando um buffer de um byte,
então apenas uma variável temporária, apenas

3228
02:36:30,790 --> 02:36:33,090
>como a temperatura de Brian ou o copo vazio.

3229
02:36:33,090 --> 02:36:35,160
>E estou usando essa função, fread.

3230
02:36:35,160 --> 02:36:39,750
>Estou lendo naquele buffer por meio de
seu endereço, do tamanho de um byte,

3231
02:36:39,750 --> 02:36:42,870
>especificamente um byte
do arquivo de origem.

3232
02:36:42,870 --> 02:36:47,940
>E então, nesse mesmo loop, estou escrevendo
desse buffer, do tamanho de um byte,

3233
02:36:47,940 --> 02:36:50,950
>especificamente um byte,
para o destino.

3234
02:36:50,950 --> 02:36:53,760
>Então, o programa CP
que você deve ter me visto usar

3235
02:36:53,760 --> 02:36:57,090
>ou você mesmo usou para copiar arquivos,
está literalmente fazendo isso.

3236
02:36:57,090 --> 02:36:59,790
>está abrindo um arquivo,
iterando sobre todos os seus bytes,

3237
02:36:59,790 --> 02:37:02,010
>e copiando da
origem ao destino.

3238
02:37:02,010 --> 02:37:04,260
>E por último, está fechando o arquivo.

3239
02:37:04,260 --> 02:37:06,360
>E esses dois últimos exemplos
deliberadamente rápidos,

3240
02:37:06,360 --> 02:37:11,130
>porque toda esta semana será gasta
mergulhando em I/O de arquivos e imagens

3241
02:37:11,130 --> 02:37:11,890
>como esses.

3242
02:37:11,890 --> 02:37:16,560
>Mas tudo o que fizemos foi usar esses
fread, fopen e fwrite e f close,

3243
02:37:16,560 --> 02:37:18,610
>para manipular esses mesmos arquivos.

3244
02:37:18,610 --> 02:37:21,975
>Então, por exemplo, se eu fizer
isso agora, deixe-me fazer make cp.

3245
02:37:21,975 --> 02:37:25,800
>OK, parece compilar,
./ cp, brian.jpeg.

3246
02:37:25,800 --> 02:37:27,750
>Que tal brian2.jpeg?
3247
02:37:27,750 --> 02:37:28,680
>E Enter.

3248
02:37:28,680 --> 02:37:29,880
>Parece que nada aconteceu.

3249
02:37:29,880 --> 02:37:33,240
>Mas se eu entrar aqui e
clicar duas vezes em brian2,

3250
02:37:33,240 --> 02:37:37,420
>vemos que temos uma segunda
cópia do arquivo real de Brian.

3251
02:37:37,420 --> 02:37:41,560
>Portanto, na próxima semana, você experimentará
vários formatos de arquivo para imagens.

3252
02:37:41,560 --> 02:37:42,580
>O primeiro é jpeg.

3253
02:37:42,580 --> 02:37:45,000
>E nós daremos a você a
chamada imagem forense

3254
02:37:45,000 --> 02:37:47,938
>de um monte de fotos de um
cartão de memória digital.

3255
02:37:47,938 --> 02:37:50,730
>Na verdade, é muito comum hoje em
dia, certamente na aplicação do Direito,

3256
02:37:50,730 --> 02:37:53,580
>fazer cópias forenses de discos
rígidos, de dispositivos de mídia,

3257
02:37:53,580 --> 02:37:55,920
>de telefones e outros dispositivos,
e então analisá-los

3258
02:37:55,920 --> 02:37:58,650
>em busca de dados perdidos,
corrompidos ou excluídos.

3259
02:37:58,650 --> 02:38:01,980
>Faremos exatamente isso, onde,
você vai escrever um programa que recupera

3260
02:38:01,980 --> 02:38:05,850
>JPEGs que foram excluídos acidentalmente
de um cartão de memória digital.

3261
02:38:05,850 --> 02:38:08,100
>E nós daremos a você todas as
cópias desse cartão de memória

3262
02:38:08,100 --> 02:38:11,220
>fazendo uma imagem forense disso,
que está copiando todos os 0's e 1's

3263
02:38:11,220 --> 02:38:13,710
>de uma câmera e entregando
a você em um arquivo

3264
02:38:13,710 --> 02:38:16,710
>que você pode abrir e escrever.

3265
02:38:16,710 --> 02:38:18,930
>Também apresentaremos
os arquivos de bitmap,

3266
02:38:18,930 --> 02:38:22,290
>BMP's, popularizado pelo
funcionamento do Windows

3267
02:38:22,290 --> 02:38:24,160
>com uso principal em papéis de parede
e similares.

3268
02:38:24,160 --> 02:38:28,470
>Mas vamos usá-los para implementar
usando ponteiros e I/O de arquivo,

3269
02:38:28,470 --> 02:38:30,550
>seu próprio filtro semelhante ao do Instagram.

3270
02:38:30,550 --> 02:38:33,540
>Então, vamos tirar esta foto,
aqui, da passarela do Weeks

3271
02:38:33,540 --> 02:38:35,578
>aqui em Cambridge,
Massachusetts - Harvard.

3272
02:38:35,578 --> 02:38:37,620
>E vamos implementar
uma série de filtros,

3273
02:38:37,620 --> 02:38:39,328
>tomando esta imagem
original, por exemplo,

3274
02:38:39,328 --> 02:38:41,910
>e dessaturando-a,
tornando-a preto e branco,

3275
02:38:41,910 --> 02:38:45,210
>iterando sobre todos os pixels de cima
para baixo, da esquerda para a direita,

3276
02:38:45,210 --> 02:38:49,350
>e reconhecendo todas as cores, como vermelho,
verde, azul ou qualquer coisa intermediária,

3277
02:38:49,350 --> 02:38:53,467
>e mudá-las para algum tom de
cinza, fazendo um filtro sépia,

3278
02:38:53,467 --> 02:38:55,800
>fazendo as coisas parecerem antigas,
como esta foto tirada

3279
02:38:55,800 --> 02:39:00,810
>muitos anos atrás, aplicando da mesma forma
uma heurística que altera as cores de todos

3280
02:39:00,810 --> 02:39:02,345
>os pixels nesta imagem.

3281
02:39:02,345 --> 02:39:05,220
>Vamos fazer com que você vire
para colocar esse pixel aqui

3282
02:39:05,220 --> 02:39:06,630
>e este pixel ali.

3283
02:39:06,630 --> 02:39:09,690
>E você apreciará exatamente como
os arquivos são implementados

3284
02:39:09,690 --> 02:39:12,180
>dentro de seu próprio disco rígido e telefone.

3285
02:39:12,180 --> 02:39:17,580
>E você vai até implementar, por exemplo,
um filtro de desfoque, que não por acaso,

3286
02:39:17,580 --> 02:39:20,010
>torna mais difícil ver o
que está acontecendo aqui,

3287
02:39:20,010 --> 02:39:23,700
>porque você está começando a, agora,
calcular a média dos pixels que estão próximos

3288
02:39:23,700 --> 02:39:27,090
>uns aos outros para encobrir
as coisas e deliberadamente

3289
02:39:27,090 --> 02:39:28,990
>tornar mais difícil ver aqui.

3290
02:39:28,990 --> 02:39:30,733
>E então nós ainda, se
você quiser, teremos

3291
02:39:30,733 --> 02:39:33,150
>você implementando detecção de borda,
se ficar melhor para você,

3292
02:39:33,150 --> 02:39:37,020
>onde você encontrará bordas de todos
os objetos físicos nessas imagens,

3293
02:39:37,020 --> 02:39:43,350
>a fim de detectá-las no código
e criar uma arte visual como esta.

3294
02:39:43,350 --> 02:39:44,220
>Agora, isso é muita coisa.

3295
02:39:44,220 --> 02:39:45,960
>E eu sei que os ponteiros
são geralmente considerados
3296
02:39:45,960 --> 02:39:47,820
>estar entre os recursos
mais desafiadores do C,

3297
02:39:47,820 --> 02:39:49,403
>e certamente, programação em geral.

3298
02:39:49,403 --> 02:39:52,140
>Então, se você está sentindo
que já viu muita coisa, foi isso mesmo.

3299
02:39:52,140 --> 02:39:55,290
>Mas agora você tem a
habilidade, tanto hoje

3300
02:39:55,290 --> 02:39:59,040
>ou em um prazo muito próximo, para entender
até mesmo quadrinhos XKCD como a maioria

3301
02:39:59,040 --> 02:40:00,990
>dos cientistas
da computação.

3302
02:40:00,990 --> 02:40:05,130
>Então, nosso look final para você,
hoje, está essa brincadeira aqui.

3303
02:40:05,130 --> 02:40:10,050
>E mesmo que eu não possa
necessariamente ouvir você de longe,

3304
02:40:10,050 --> 02:40:12,690
>vou apenas assumir, em nossos
momentos finais de hoje,

3305
02:40:12,690 --> 02:40:16,650
>que todo mundo está explodindo
em uma gargalhada muito nerd.

3306
02:40:16,650 --> 02:40:19,530
>E vejo alguns sorrisos, pelo
menos, o que é reconfortante.

3307
02:40:19,530 --> 02:40:21,480
>Este foi, então, o CS50.

3308
02:40:21,480 --> 02:40:23,010
>Nos vemos na próxima.

3309
02:40:23,010 --> 02:40:26,360
>[MÚSICA, TOCANDO]

Você também pode gostar