1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [Seção 4 - Mais Confortável] 2 00:00:02,520 --> 00:00:04,850 [Rob Bowden - Harvard University] 3 00:00:04,850 --> 00:00:07,370 [Esta é CS50. - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 Temos um teste amanhã, caso vocês não sabiam disso. 5 00:00:14,810 --> 00:00:20,970 É basicamente sobre tudo o que você poderia ter visto em aula ou deveria ter visto em sala de aula. 6 00:00:20,970 --> 00:00:26,360 Isso inclui ponteiros, apesar de serem um tema muito recente. 7 00:00:26,360 --> 00:00:29,860 Você deve pelo menos entender os altos níveis de los. 8 00:00:29,860 --> 00:00:34,760 Qualquer coisa que se foi em classe, você deve entender para o quiz. 9 00:00:34,760 --> 00:00:37,320 Então se você tem perguntas sobre eles, você pode perguntar-lhes agora. 10 00:00:37,320 --> 00:00:43,280 Mas esta vai ser uma sessão muito liderado por estudantes, onde vocês perguntas, 11 00:00:43,280 --> 00:00:45,060 por isso espero que as pessoas têm perguntas. 12 00:00:45,060 --> 00:00:48,020 Alguém tem dúvidas? 13 00:00:49,770 --> 00:00:52,090 Sim. >> [Aluno] pode ir mais de ponteiros de novo? 14 00:00:52,090 --> 00:00:54,350 Eu vou passar por cima de ponteiros. 15 00:00:54,350 --> 00:00:59,180 Todas as suas variáveis, necessariamente, viver na memória, 16 00:00:59,180 --> 00:01:04,450 mas geralmente você não se preocupe com isso e você acabou de dizer x + 2 e + 3 y 17 00:01:04,450 --> 00:01:07,080 eo compilador irá descobrir onde as coisas estão a viver para você. 18 00:01:07,080 --> 00:01:12,990 Uma vez que você está lidando com ponteiros, agora você está explicitamente usando os endereços de memória. 19 00:01:12,990 --> 00:01:19,800 Assim, uma única variável só vai viver em um único endereço a qualquer momento. 20 00:01:19,800 --> 00:01:24,040 Se queremos declarar um ponteiro, que é o tipo vai parecer? 21 00:01:24,040 --> 00:01:26,210 >> Quero declarar um ponteiro p. O que faz o tipo de aparência? 22 00:01:26,210 --> 00:01:33,530 [Estudante] int * p. Sim >>. Assim, int * p. 23 00:01:33,530 --> 00:01:38,030 E como faço para torná-lo apontar para x? >> [Aluno] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Bowden] Então comercial é chamado literalmente o endereço do operador. 25 00:01:45,300 --> 00:01:50,460 Portanto, quando digo & x está ficando o endereço de memória da variável x. 26 00:01:50,460 --> 00:01:56,790 Então agora eu tenho o ponteiro p, e em qualquer lugar no meu código eu posso usar p * 27 00:01:56,790 --> 00:02:02,960 ou eu poderia usar x e vai ser exatamente a mesma coisa. 28 00:02:02,960 --> 00:02:09,520 (* P). O que se está fazendo? O que significa que a estrela significa? 29 00:02:09,520 --> 00:02:13,120 [Estudante] Significa um valor nesse ponto. Sim >>. 30 00:02:13,120 --> 00:02:17,590 Então, se olharmos para ele, pode ser muito útil para tirar os diagramas 31 00:02:17,590 --> 00:02:22,230 onde esta é uma pequena caixa de memória para x, que acontece de ter o valor 4, 32 00:02:22,230 --> 00:02:25,980 então temos uma pequena caixa de memória para p, 33 00:02:25,980 --> 00:02:31,590 e assim p aponta para x, para que desenhe uma seta de p para x. 34 00:02:31,590 --> 00:02:40,270 Assim, quando dizemos p * estamos dizendo ir para a caixa que é p. 35 00:02:40,270 --> 00:02:46,480 Star é seguir a seta e, em seguida, fazer o que quiser com essa caixa aí. 36 00:02:46,480 --> 00:03:01,090 Então eu posso dizer * p = 7, e que irá para o caixa que é x e mudança que a 7. 37 00:03:01,090 --> 00:03:13,540 Ou eu poderia dizer int z = * p * 2; Isso é confuso porque é estrela estrela. 38 00:03:13,540 --> 00:03:19,230 A estrela é uma dereferencing p, a outra estrela está se multiplicando por 2. 39 00:03:19,230 --> 00:03:26,780 Repare que eu poderia ter tão bem substituiu o p * com x. 40 00:03:26,780 --> 00:03:29,430 Você pode usá-los da mesma forma. 41 00:03:29,430 --> 00:03:38,000 E mais tarde eu posso ter ponto p para uma coisa completamente nova. 42 00:03:38,000 --> 00:03:42,190 Só posso dizer p = &z; 43 00:03:42,190 --> 00:03:44,940 Então, agora p sem pontos mais longos para x, que aponta para z. 44 00:03:44,940 --> 00:03:50,510 E a qualquer momento que eu faço p * é o mesmo que fazer z. 45 00:03:50,510 --> 00:03:56,170 Então a única coisa útil sobre isso é quando começamos a entrar em funções. 46 00:03:56,170 --> 00:03:59,790 >> É uma espécie de inútil para declarar um ponteiro que aponta para algo 47 00:03:59,790 --> 00:04:03,140 e então você está apenas dereferencing-lo 48 00:04:03,140 --> 00:04:06,060 quando você poderia ter usado a variável original para começar. 49 00:04:06,060 --> 00:04:18,190 Mas quando você entra em funções - então vamos dizer que temos alguma função, int foo, 50 00:04:18,190 --> 00:04:32,810 que leva um ponteiro e só faz * p = 6; 51 00:04:32,810 --> 00:04:39,990 Como vimos antes, com swap, você não pode fazer um swap de efetivo e uma função separada 52 00:04:39,990 --> 00:04:45,180 por apenas passando inteiros porque tudo na C está sempre passando por valor. 53 00:04:45,180 --> 00:04:48,360 Mesmo quando você está passando ponteiros você está passando por valor. 54 00:04:48,360 --> 00:04:51,940 O que acontece é que esses valores são endereços de memória. 55 00:04:51,940 --> 00:05:00,770 Portanto, quando digo foo (p), eu estou passando o ponteiro para a função foo 56 00:05:00,770 --> 00:05:03,910 e, em seguida, faz foo * p = 6; 57 00:05:03,910 --> 00:05:08,600 Assim, dentro dessa função, * p é ainda equivalente a x, 58 00:05:08,600 --> 00:05:12,720 mas eu não posso usar x dentro dessa função, porque não é escopo dentro dessa função. 59 00:05:12,720 --> 00:05:19,510 Então * p = 6 é a única maneira que eu posso acessar uma variável local de outra função. 60 00:05:19,510 --> 00:05:23,600 Ou, bem, os ponteiros são a única maneira que eu posso acessar uma variável local de outra função. 61 00:05:23,600 --> 00:05:31,600 [Aluno] Digamos que você queria voltar para um ponteiro. Como exatamente você faz isso? 62 00:05:31,600 --> 00:05:44,270 [Bowden] Retornar um ponteiro como em algo como int y = 3; retorno & y? >> [Estudante] Yeah. 63 00:05:44,270 --> 00:05:48,480 [Bowden] Okay. Você nunca deve fazer isso. Isso é ruim. 64 00:05:48,480 --> 00:05:59,480 Eu acho que vi nestes slides das aulas que começaram a ver neste diagrama toda a memória 65 00:05:59,480 --> 00:06:02,880 onde até aqui você tem endereço de memória 0 66 00:06:02,880 --> 00:06:09,550 e aqui você tem de endereço de memória 4 GB ou 2 elevado à 32. 67 00:06:09,550 --> 00:06:15,120 Então você tem algumas coisas e algumas coisas e então você tem a sua pilha 68 00:06:15,120 --> 00:06:21,780 e você tem a sua pilha, que você só começou a aprender sobre, crescendo. 69 00:06:21,780 --> 00:06:24,390 [Aluno] não é a pilha acima da pilha? 70 00:06:24,390 --> 00:06:27,760 >> Sim. A pilha é em cima, não é? >> [Aluno] Bem, ele colocou 0 em cima. 71 00:06:27,760 --> 00:06:30,320 [Estudante] Oh, ele colocou 0 em cima. >> [Aluno] Ah, ok. 72 00:06:30,320 --> 00:06:36,060 Disclaimer: Qualquer lugar com CS50 você vai vê-lo desta maneira. >> [Aluno] Okay. 73 00:06:36,060 --> 00:06:40,290 É que quando você está vendo primeiro pilhas, 74 00:06:40,290 --> 00:06:45,000 como quando você pensar em uma pilha você acha de empilhar as coisas em cima da outra. 75 00:06:45,000 --> 00:06:50,810 Então, temos a tendência de virar esta em torno de modo a pilha está crescendo como uma pilha normalmente 76 00:06:50,810 --> 00:06:55,940 em vez da pilha pendurada para baixo. >> [Aluno] não montes tecnicamente crescer muito, embora? 77 00:06:55,940 --> 00:07:01,100 Depende do que você entende por crescer. 78 00:07:01,100 --> 00:07:04,010 A pilha e heap crescer sempre em direções opostas. 79 00:07:04,010 --> 00:07:09,420 Uma pilha é sempre crescendo no sentido de que ele está crescendo 80 00:07:09,420 --> 00:07:12,940 para endereços de memória mais altas, ea pilha está crescendo para baixo 81 00:07:12,940 --> 00:07:17,260 em que é crescente para endereços menores de memória. 82 00:07:17,260 --> 00:07:20,250 Assim, o topo é 0 e no fundo é endereços de memória de alta. 83 00:07:20,250 --> 00:07:26,390 Ambos estão crescendo, apenas em direções opostas. 84 00:07:26,390 --> 00:07:29,230 [Estudante] Eu só quis dizer que porque você disse que colocar pilha na parte inferior 85 00:07:29,230 --> 00:07:33,640 porque parece mais intuitivo porque, para a pilha para começar no topo de uma pilha, 86 00:07:33,640 --> 00:07:37,520 pilha é em cima de si também, então isso é - >> Yeah. 87 00:07:37,520 --> 00:07:44,960 Você também acha da pilha como o crescimento e maior, mas a pilha mais. 88 00:07:44,960 --> 00:07:50,280 Assim, a pilha é o que nós meio que queremos mostrar crescendo. 89 00:07:50,280 --> 00:07:55,390 Mas em todo lugar que você olha de outra forma vai mostrar o endereço 0 no topo 90 00:07:55,390 --> 00:07:59,590 eo endereço de memória mais alto na parte inferior, por isso esta é a sua visão usual de memória. 91 00:07:59,590 --> 00:08:02,100 >> Você tem uma pergunta? 92 00:08:02,100 --> 00:08:04,270 [Aluno] Você pode nos dizer mais sobre o monte? 93 00:08:04,270 --> 00:08:06,180 Sim. Eu vou chegar a isso em um segundo. 94 00:08:06,180 --> 00:08:12,220 Primeiro, por que voltar para devolver & y é uma coisa ruim, 95 00:08:12,220 --> 00:08:18,470 na pilha você tem um monte de quadros de pilha que representam todas as funções 96 00:08:18,470 --> 00:08:20,460 que foram chamados. 97 00:08:20,460 --> 00:08:27,990 Então, ignorando as coisas anteriores, o topo da sua pilha é sempre vai ser a função principal 98 00:08:27,990 --> 00:08:33,090 já que é a primeira função que está sendo chamado. 99 00:08:33,090 --> 00:08:37,130 E então quando você chamar uma outra função, a pilha vai crescer para baixo. 100 00:08:37,130 --> 00:08:41,640 Então, se eu chamar alguma função, foo, e torna-se sua estrutura própria pilha, 101 00:08:41,640 --> 00:08:47,280 ele pode chamar alguma função bar,, que recebe o seu quadro de pilha própria. 102 00:08:47,280 --> 00:08:49,840 E bar pode ser recursiva e que poderia chamar-se, 103 00:08:49,840 --> 00:08:54,150 e para que segunda chamada para a barra vai ficar sua estrutura própria pilha. 104 00:08:54,150 --> 00:08:58,880 E assim o que se passa nestes quadros de pilha são todas as variáveis ​​locais 105 00:08:58,880 --> 00:09:03,450 e todos os argumentos da função que - 106 00:09:03,450 --> 00:09:08,730 Todas as coisas que estão no local delimitado para esta função vai nesses quadros de pilha. 107 00:09:08,730 --> 00:09:21,520 Então isso significa que quando eu disse algo como bar é uma função, 108 00:09:21,520 --> 00:09:29,270 Eu só vou declarar um inteiro e, em seguida, retornar um ponteiro para esse inteiro. 109 00:09:29,270 --> 00:09:33,790 Então onde é que y viver? 110 00:09:33,790 --> 00:09:36,900 [Estudante] y vive no bar. >> [Bowden] Yeah. 111 00:09:36,900 --> 00:09:45,010 Em algum lugar neste pequeno quadrado de memória é uma praça que tem littler y nele. 112 00:09:45,010 --> 00:09:53,370 Quando eu voltar & y, estou retornando um ponteiro para esse pequeno bloco de memória. 113 00:09:53,370 --> 00:09:58,400 Mas então, quando a função retorna, o seu quadro de pilha é pego na pilha. 114 00:10:01,050 --> 00:10:03,530 E é por isso que ele é chamado de pilha. 115 00:10:03,530 --> 00:10:06,570 É como a estrutura de dados de pilha, se você sabe o que é. 116 00:10:06,570 --> 00:10:11,580 Ou até mesmo como uma pilha de bandejas é sempre o exemplo, 117 00:10:11,580 --> 00:10:16,060 principal está a ir na parte inferior, em seguida, a função de primeiro ligar está a ir em cima do que, 118 00:10:16,060 --> 00:10:20,400 e você não pode voltar ao principal até retornar de todas as funções que foram chamados 119 00:10:20,400 --> 00:10:22,340 que foram colocados na parte superior do mesmo. 120 00:10:22,340 --> 00:10:28,650 >> [Aluno] Então, se você realmente fez retornar a Y &, esse valor está sujeito a alteração sem aviso prévio. 121 00:10:28,650 --> 00:10:31,290 Sim, é - >> [aluno] Poderia ser substituído. Sim >>. 122 00:10:31,290 --> 00:10:34,660 É completamente - Se você tentar - 123 00:10:34,660 --> 00:10:38,040 Esta seria também uma barra * int porque ele está retornando um ponteiro, 124 00:10:38,040 --> 00:10:41,310 assim, seu tipo de retorno é int *. 125 00:10:41,310 --> 00:10:46,500 Se você tentar usar o valor de retorno dessa função, é um comportamento indefinido 126 00:10:46,500 --> 00:10:51,770 porque esse ponteiro aponta para a memória ruim. >> [Aluno] Okay. 127 00:10:51,770 --> 00:11:01,250 Então, o que se, por exemplo, você declarou int * y = malloc (sizeof (int))? 128 00:11:01,250 --> 00:11:03,740 Assim é melhor. Sim. 129 00:11:03,740 --> 00:11:07,730 [Aluno] Nós conversamos sobre como quando arrastar as coisas para a nossa lixeira 130 00:11:07,730 --> 00:11:11,750 eles não estão realmente apagado, nós só perdem seus ponteiros. 131 00:11:11,750 --> 00:11:15,550 Portanto, neste caso nós realmente apagar o valor ou é ainda existe na memória? 132 00:11:15,550 --> 00:11:19,130 Para a maior parte, ele vai estar lá. 133 00:11:19,130 --> 00:11:24,220 Mas vamos dizer que acontecer para chamar alguma outra função, Baz. 134 00:11:24,220 --> 00:11:28,990 Baz vai ficar sua estrutura própria pilha aqui. 135 00:11:28,990 --> 00:11:31,470 Vai ser a substituição de todas essas coisas, 136 00:11:31,470 --> 00:11:34,180 e então se você tentar mais tarde e usar o ponteiro que você tem antes, 137 00:11:34,180 --> 00:11:35,570 ele não vai ser o mesmo valor. 138 00:11:35,570 --> 00:11:38,150 Vai ter mudado só porque você chamou o baz função. 139 00:11:38,150 --> 00:11:43,080 [Aluno] Mas se não tivéssemos, estaríamos ainda obter 3? 140 00:11:43,080 --> 00:11:44,990 [Bowden] Em toda a probabilidade, você o faria. 141 00:11:44,990 --> 00:11:49,670 Mas você não pode contar com isso. C apenas diz comportamento indefinido. 142 00:11:49,670 --> 00:11:51,920 >> [Estudante] Oh, é verdade. Okay. 143 00:11:51,920 --> 00:11:58,190 Então, quando você quiser retornar um ponteiro, este é o lugar onde malloc vem em uso. 144 00:12:00,930 --> 00:12:15,960 Eu estou escrevendo na verdade, apenas retornar malloc (3 * sizeof (int)). 145 00:12:17,360 --> 00:12:24,050 Nós falaremos sobre malloc mais em um segundo, mas a idéia de malloc é tudo de suas variáveis ​​locais 146 00:12:24,050 --> 00:12:26,760 sempre vão para a pilha. 147 00:12:26,760 --> 00:12:31,570 Qualquer coisa que é malloced vai na pilha, e será para sempre e sempre na pilha 148 00:12:31,570 --> 00:12:34,490 até que você explicitamente libertá-lo. 149 00:12:34,490 --> 00:12:42,130 Então isso significa que quando você malloc alguma coisa, ele vai sobreviver após o retorno da função. 150 00:12:42,130 --> 00:12:46,800 [Aluno] Será que vai sobreviver depois que o programa pára de correr? Não. >> 151 00:12:46,800 --> 00:12:53,180 Ok, então ele vai estar lá até que o programa é todo o caminho feito em execução. Sim >>. 152 00:12:53,180 --> 00:12:57,510 Podemos ir mais detalhes do que acontece quando o programa pára de funcionar. 153 00:12:57,510 --> 00:13:02,150 Você pode precisar para me lembrar, mas que é uma coisa separada inteiramente. 154 00:13:02,150 --> 00:13:04,190 [Estudante] Então malloc cria um ponteiro? Sim >>. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [estudante] Eu acho que malloc designa um bloco de memória que um ponteiro pode usar. 156 00:13:15,400 --> 00:13:19,610 [Bowden] Eu quero que diagrama novamente. >> [Aluno] Então, essa função funciona, embora? 157 00:13:19,610 --> 00:13:26,430 [Aluno] Sim, malloc designa um bloco de memória que você pode usar, 158 00:13:26,430 --> 00:13:30,470 e, em seguida, retorna o endereço do primeiro bloco de memória que. 159 00:13:30,470 --> 00:13:36,750 >> [Bowden] Yeah. Então, quando malloc você, você está pegando um bloco de memória 160 00:13:36,750 --> 00:13:38,260 que está atualmente no heap. 161 00:13:38,260 --> 00:13:43,040 Se a pilha é muito pequeno, então a pilha só vai crescer, e cresce nessa direção. 162 00:13:43,040 --> 00:13:44,650 Então, digamos que a pilha é muito pequeno. 163 00:13:44,650 --> 00:13:49,960 Então, ele está prestes a crescer um pouco e retornar um ponteiro para este bloco que só cresceu. 164 00:13:49,960 --> 00:13:55,130 Quando o material livre, você está fazendo mais espaço no heap, 165 00:13:55,130 --> 00:14:00,030 Então uma chamada posterior para malloc pode reutilizar que a memória que você já tinha libertado. 166 00:14:00,030 --> 00:14:09,950 A coisa importante sobre malloc e free é que lhe dá o controle completo 167 00:14:09,950 --> 00:14:12,700 sobre a vida destes blocos de memória. 168 00:14:12,700 --> 00:14:15,420 As variáveis ​​globais são sempre vivo. 169 00:14:15,420 --> 00:14:18,500 As variáveis ​​locais estão vivos dentro de seu alcance. 170 00:14:18,500 --> 00:14:22,140 Assim que você passar uma chaveta, as variáveis ​​locais estão mortos. 171 00:14:22,140 --> 00:14:28,890 Memória Malloced está vivo quando você quiser estar vivo 172 00:14:28,890 --> 00:14:33,480 e depois é liberado quando você diga a ele para ser lançado. 173 00:14:33,480 --> 00:14:38,420 Esses são realmente os únicos três tipos de memória, realmente. 174 00:14:38,420 --> 00:14:41,840 Há gerenciamento automático de memória, que é a pilha. 175 00:14:41,840 --> 00:14:43,840 As coisas acontecem automaticamente para você. 176 00:14:43,840 --> 00:14:46,910 Quando você diz int x, memória é alocada para int x. 177 00:14:46,910 --> 00:14:51,630 Quando x sai do escopo, a memória é recuperado para x. 178 00:14:51,630 --> 00:14:54,790 Depois, há o gerenciamento de memória dinâmica, que é o que malloc é, 179 00:14:54,790 --> 00:14:56,740 que é quando você tem controle. 180 00:14:56,740 --> 00:15:01,290 Você decidir dinamicamente quando a memória deve e não deve ser alocado. 181 00:15:01,290 --> 00:15:05,050 E depois há o estático, que apenas significa que ele vive para sempre, 182 00:15:05,050 --> 00:15:06,610 que é o que as variáveis ​​globais são. 183 00:15:06,610 --> 00:15:10,240 Eles são apenas sempre na memória. 184 00:15:10,960 --> 00:15:12,760 >> Perguntas? 185 00:15:14,490 --> 00:15:17,230 [Estudante] Você pode definir um bloco de apenas usando chaves 186 00:15:17,230 --> 00:15:21,220 mas não ter que ter um? se declaração ou uma declaração de tempo ou algo assim 187 00:15:21,220 --> 00:15:29,130 Você pode definir um bloco como em uma função, mas que tem chaves também. 188 00:15:29,130 --> 00:15:32,100 [Aluno] Então, você não pode apenas ter como um par aleatório de chaves no seu código 189 00:15:32,100 --> 00:15:35,680 que têm variáveis ​​locais? >> Sim, você pode. 190 00:15:35,680 --> 00:15:45,900 Dentro do bar int poderíamos ter {int y = 3;}. 191 00:15:45,900 --> 00:15:48,440 Isso deveria estar aqui. 192 00:15:48,440 --> 00:15:52,450 Mas que define completamente o escopo de int y. 193 00:15:52,450 --> 00:15:57,320 Depois que chaveta segundo, y não pode ser mais usado. 194 00:15:57,910 --> 00:16:00,630 Você quase nunca fazem isso, no entanto. 195 00:16:02,940 --> 00:16:07,370 Voltando ao que acontece quando um programa termina, 196 00:16:07,370 --> 00:16:18,760 há uma espécie de mentira equívoco / meia que damos a fim de apenas fazer as coisas mais fáceis. 197 00:16:18,760 --> 00:16:24,410 Nós dizemos a vocês que quando você alocar memória 198 00:16:24,410 --> 00:16:29,860 você está alocando algum pedaço de memória RAM para essa variável. 199 00:16:29,860 --> 00:16:34,190 Mas você não está realmente tocar directamente RAM sempre em seus programas. 200 00:16:34,190 --> 00:16:37,490 Se você pensar sobre isso, como eu desenhei - 201 00:16:37,490 --> 00:16:44,330 E, na verdade, se você passar no GDB você vai ver a mesma coisa. 202 00:16:51,120 --> 00:16:57,590 Independentemente do número de vezes que você executar o programa ou o programa que está em execução, 203 00:16:57,590 --> 00:16:59,950 a pilha sempre vai começar - 204 00:16:59,950 --> 00:17:06,510 você sempre vai ver variáveis ​​em torno de algo oxbffff endereço. 205 00:17:06,510 --> 00:17:09,470 É geralmente em algum lugar na região. 206 00:17:09,470 --> 00:17:18,760 Mas como pode, eventualmente, ter dois programas de ponteiros para a memória mesmo? 207 00:17:20,640 --> 00:17:27,650 [Aluno] Há alguma designação arbitrária de onde oxbfff é suposto ser na RAM 208 00:17:27,650 --> 00:17:31,320 que pode realmente estar em lugares diferentes, dependendo de quando a função foi chamada. 209 00:17:31,320 --> 00:17:35,920 Sim. O termo é a memória virtual. 210 00:17:35,920 --> 00:17:42,250 A idéia é que cada processo único, cada programa que está em execução no computador 211 00:17:42,250 --> 00:17:49,450 tem o seu próprio - vamos supor que 32 bits - espaço de endereçamento completamente independente. 212 00:17:49,450 --> 00:17:51,590 Este é o espaço de endereço. 213 00:17:51,590 --> 00:17:56,220 Ele tem suas próprias completamente independentes 4 gigabytes de usar. 214 00:17:56,220 --> 00:18:02,220 >> Então, se você executar dois programas simultaneamente, este programa vê quatro gigabytes para si, 215 00:18:02,220 --> 00:18:04,870 este programa vê quatro gigabytes para si, 216 00:18:04,870 --> 00:18:07,720 e é impossível para este programa dereference um ponteiro 217 00:18:07,720 --> 00:18:10,920 e acabar com a memória a partir deste programa. 218 00:18:10,920 --> 00:18:18,200 E o que a memória virtual é um mapeamento de um espaço de endereço de processos 219 00:18:18,200 --> 00:18:20,470 a coisas reais na RAM. 220 00:18:20,470 --> 00:18:22,940 Portanto, cabe ao seu sistema operacional para saber que, 221 00:18:22,940 --> 00:18:28,080 hey, quando esse cara oxbfff ponteiro dereferences, que realmente significa 222 00:18:28,080 --> 00:18:31,040 que ele quer RAM byte 1000, 223 00:18:31,040 --> 00:18:38,150 enquanto que se este programa oxbfff dereferences, ele realmente quer RAM byte 10000. 224 00:18:38,150 --> 00:18:41,590 Eles podem ser arbitrariamente afastadas. 225 00:18:41,590 --> 00:18:48,730 Isto é mesmo verdade das coisas dentro de um espaço único de processos de endereço. 226 00:18:48,730 --> 00:18:54,770 Então, como se vê todos os 4 gigabytes para si mesmo, mas vamos dizer - 227 00:18:54,770 --> 00:18:57,290 [Aluno] Será que cada processo - 228 00:18:57,290 --> 00:19:01,350 Vamos dizer que você tem um computador com apenas 4 gigabytes de memória RAM. 229 00:19:01,350 --> 00:19:06,430 A cada processo ver toda a 4 gigabytes? Sim >>. 230 00:19:06,430 --> 00:19:13,060 Mas os 4 gigabytes que vê é uma mentira. 231 00:19:13,060 --> 00:19:20,460 É só ele acha que tem toda a memória isso porque não conhece nenhum outro processo existe. 232 00:19:20,460 --> 00:19:28,140 É só usar a memória, tanto quanto ele realmente precisa. 233 00:19:28,140 --> 00:19:32,340 O sistema operacional não vai dar RAM para este processo 234 00:19:32,340 --> 00:19:35,750 se não for usar qualquer memória em toda essa região. 235 00:19:35,750 --> 00:19:39,300 Não vai dar-lhe a memória para essa região. 236 00:19:39,300 --> 00:19:54,780 Mas a idéia é que - eu estou tentando pensar - Eu não consigo pensar em uma analogia. 237 00:19:54,780 --> 00:19:56,780 Analogias são difíceis. 238 00:19:57,740 --> 00:20:02,700 Uma das questões de memória virtual ou uma das coisas que ele está resolvendo 239 00:20:02,700 --> 00:20:06,810 é a de que os processos devem ser completamente alheios um ao outro. 240 00:20:06,810 --> 00:20:12,140 E assim você pode escrever qualquer programa que apenas dereferences qualquer ponteiro, 241 00:20:12,140 --> 00:20:19,340 como apenas escrever um programa que diz * (ox1234), 242 00:20:19,340 --> 00:20:22,890 e isso é o endereço de memória dereferencing 1234. 243 00:20:22,890 --> 00:20:28,870 >> Mas cabe ao sistema operacional para depois traduzir o que significa 1234. 244 00:20:28,870 --> 00:20:33,960 Assim, se 1234 acontece de ser um endereço de memória válido para este processo, 245 00:20:33,960 --> 00:20:38,800 como é na pilha ou algo assim, então isso vai devolver o valor do endereço de memória 246 00:20:38,800 --> 00:20:41,960 na medida em que o processo sabe. 247 00:20:41,960 --> 00:20:47,520 Mas se 1234 não é um endereço válido, como acontece à terra 248 00:20:47,520 --> 00:20:52,910 em algum pedaço de memória aqui que está além da pilha e além da pilha 249 00:20:52,910 --> 00:20:57,200 e você realmente não tenho usado que, em seguida, que é quando você fazer as coisas como segfaults 250 00:20:57,200 --> 00:21:00,260 porque você está tocando memória que você não deve tocar. 251 00:21:07,180 --> 00:21:09,340 Isso também é verdadeiro - 252 00:21:09,340 --> 00:21:15,440 Um sistema de 32 bits, 32 bits significa que você tem 32 bits para definir um endereço de memória. 253 00:21:15,440 --> 00:21:22,970 É por isso que os ponteiros são 8 bytes, porque 32 bits são 8 bytes - ou 4 bytes. 254 00:21:22,970 --> 00:21:25,250 Os ponteiros são 4 bytes. 255 00:21:25,250 --> 00:21:33,680 Então, quando você vê um ponteiro como oxbfffff, que é - 256 00:21:33,680 --> 00:21:40,080 Dentro de um determinado programa você pode apenas construir qualquer ponteiro arbitrária, 257 00:21:40,080 --> 00:21:46,330 em qualquer lugar de ox0 para boi 8 f's - ffffffff. 258 00:21:46,330 --> 00:21:49,180 [Aluno] Você não disse que eles são 4 bytes? Sim >>. 259 00:21:49,180 --> 00:21:52,730 [Aluno] Em seguida, cada byte terá - >> [Bowden] Hexadecimal. 260 00:21:52,730 --> 00:21:59,360 Hexadecimal - 5, 6, 7, 8. Então ponteiros você vai sempre ver em hexadecimal. 261 00:21:59,360 --> 00:22:01,710 É exatamente como nós classificamos ponteiros. 262 00:22:01,710 --> 00:22:05,240 A cada 2 dígitos do hexadecimal é um byte. 263 00:22:05,240 --> 00:22:09,600 Então lá vai ser de 8 dígitos hexadecimais de 4 bytes. 264 00:22:09,600 --> 00:22:14,190 Assim, cada ponteiro único em um sistema de 32 bits vai ser 4 bytes, 265 00:22:14,190 --> 00:22:18,550 o que significa que, em seu processo, você pode construir qualquer arbitrárias 4 bytes 266 00:22:18,550 --> 00:22:20,550 e fazer um ponteiro de fora, 267 00:22:20,550 --> 00:22:32,730 o que significa que, tanto quanto é consciente, pode dirigir um inteiro 2 para os 32 bytes de memória. 268 00:22:32,730 --> 00:22:34,760 Mesmo que ele realmente não tem acesso a isso, 269 00:22:34,760 --> 00:22:40,190 mesmo se o seu computador tem apenas 512 megabytes, ele acha que tem essa quantidade de memória. 270 00:22:40,190 --> 00:22:44,930 E o sistema operacional é inteligente o suficiente para que ele só irá alocar o que você realmente precisa. 271 00:22:44,930 --> 00:22:49,630 Não basta ir, oh, um novo processo: quatro shows. 272 00:22:49,630 --> 00:22:51,930 >> Sim. >> [Aluno] O que é que o boi significa? Por que você escreve? 273 00:22:51,930 --> 00:22:54,980 É apenas o símbolo para hexadecimal. 274 00:22:54,980 --> 00:22:59,590 Quando você vê um número com início boi, as coisas são sucessivas hexadecimal. 275 00:23:01,930 --> 00:23:05,760 [Aluno] Você estava explicando sobre o que acontece quando um programa termina. Sim >>. 276 00:23:05,760 --> 00:23:09,480 O que acontece quando um programa termina é o sistema operacional 277 00:23:09,480 --> 00:23:13,600 apenas apaga os mapeamentos que tem para esses endereços, e é isso. 278 00:23:13,600 --> 00:23:17,770 O sistema operacional pode agora dar apenas que a memória para outro programa para usar. 279 00:23:17,770 --> 00:23:19,490 [Aluno] Okay. 280 00:23:19,490 --> 00:23:24,800 Então, quando você aloca algo na pilha ou as variáveis ​​de pilha ou global ou qualquer coisa, 281 00:23:24,800 --> 00:23:27,010 todos eles simplesmente desaparecer assim que o programa termina 282 00:23:27,010 --> 00:23:32,120 porque o sistema operacional é agora livre para dar essa memória para qualquer outro processo. 283 00:23:32,120 --> 00:23:35,150 [Aluno] Mesmo que provavelmente há ainda valores escritos em? Sim >>. 284 00:23:35,150 --> 00:23:37,740 Os valores são provavelmente ainda está lá. 285 00:23:37,740 --> 00:23:41,570 É só isso que vai ser difícil chegar a eles. 286 00:23:41,570 --> 00:23:45,230 É muito mais difícil para chegar a eles que é para chegar a um arquivo excluído 287 00:23:45,230 --> 00:23:51,450 porque o tipo de arquivo que foi excluído fica lá por um longo tempo eo disco rígido é muito maior. 288 00:23:51,450 --> 00:23:54,120 Por isso, vai para substituir partes diferentes de memória 289 00:23:54,120 --> 00:23:58,640 antes que aconteça para substituir o pedaço de memória que o arquivo utilizado para estar. 290 00:23:58,640 --> 00:24:04,520 Mas a memória principal, memória RAM, você percorrer muito mais rápido, 291 00:24:04,520 --> 00:24:08,040 por isso vai muito rapidamente ser substituído. 292 00:24:10,300 --> 00:24:13,340 Dúvidas sobre esta ou qualquer outra coisa? 293 00:24:13,340 --> 00:24:16,130 [Aluno] Tenho dúvidas sobre um tópico diferente. Ok >>. 294 00:24:16,130 --> 00:24:19,060 Alguém tem dúvidas sobre isso? 295 00:24:20,170 --> 00:24:23,120 >> Okay. Tópico diferente. >> [Aluno] Okay. 296 00:24:23,120 --> 00:24:26,550 Eu estava passando por alguns dos testes práticos, 297 00:24:26,550 --> 00:24:30,480 e em uma delas ele estava falando sobre o sizeof 298 00:24:30,480 --> 00:24:35,630 eo valor que ele retorna ou diferentes tipos de variáveis. Sim >>. 299 00:24:35,630 --> 00:24:45,060 E disse que tanto int e longo retorno tanto 4, então ambos são 4 bytes. 300 00:24:45,060 --> 00:24:48,070 Existe alguma diferença entre um int e um longo, ou é a mesma coisa? 301 00:24:48,070 --> 00:24:50,380 Sim, há uma diferença. 302 00:24:50,380 --> 00:24:52,960 O padrão C - 303 00:24:52,960 --> 00:24:54,950 Provavelmente, vou estragar. 304 00:24:54,950 --> 00:24:58,800 O padrão C é como o que é C, a documentação oficial do C. 305 00:24:58,800 --> 00:25:00,340 Isto é o que diz. 306 00:25:00,340 --> 00:25:08,650 Assim, o padrão C apenas diz que um char para sempre e ser sempre um byte. 307 00:25:10,470 --> 00:25:19,040 Tudo o que depois - a um curto é sempre apenas definida como sendo maior do que ou igual a um char. 308 00:25:19,040 --> 00:25:23,010 Isso pode ser estritamente maior que, mas não positiva. 309 00:25:23,010 --> 00:25:31,940 Um int é apenas definida como sendo maior do que ou igual a uma curta distância. 310 00:25:31,940 --> 00:25:36,210 E um comprimento é apenas definida como sendo maior do que ou igual a um inteiro. 311 00:25:36,210 --> 00:25:41,600 E um longo tempo é maior do que ou igual a um comprimento. 312 00:25:41,600 --> 00:25:46,610 Então, a única coisa que o padrão C define é a ordenação relativa de tudo. 313 00:25:46,610 --> 00:25:54,880 A quantidade real de memória que as coisas levam-se geralmente até a sua implementação, 314 00:25:54,880 --> 00:25:57,640 Mas é muito bem definida neste momento. >> [Aluno] Okay. 315 00:25:57,640 --> 00:26:02,490 Então shorts são quase sempre vai ser de 2 bytes. 316 00:26:04,920 --> 00:26:09,950 Ints são quase sempre vai ser de 4 bytes. 317 00:26:12,070 --> 00:26:15,340 Longs longos são quase sempre vai ser de 8 bytes. 318 00:26:17,990 --> 00:26:23,160 E deseja, isso depende se você estiver usando um de 32 bits ou um sistema de 64 bits. 319 00:26:23,160 --> 00:26:27,450 Assim, um tempo que vai corresponder ao tipo de sistema. 320 00:26:27,450 --> 00:26:31,920 Se você estiver usando um sistema de 32 bits, como o aparelho, que vai ser de 4 bytes. 321 00:26:34,530 --> 00:26:42,570 Se você estiver usando uma de 64 bits como um monte de computadores mais recentes, que vai ser de 8 bytes. 322 00:26:42,570 --> 00:26:45,230 >> Ints são quase sempre 4 bytes neste momento. 323 00:26:45,230 --> 00:26:47,140 Longs longos são quase sempre de 8 bytes. 324 00:26:47,140 --> 00:26:50,300 No passado, o ints usado para ser apenas 2 bytes. 325 00:26:50,300 --> 00:26:56,840 Mas note que este satisfaz completamente todas essas relações de maior e igual a. 326 00:26:56,840 --> 00:27:01,280 Contanto é perfeitamente permitido ter o mesmo tamanho como um inteiro, 327 00:27:01,280 --> 00:27:04,030 e está também autorizado a ser do mesmo tamanho que um comprimento longo. 328 00:27:04,030 --> 00:27:11,070 E isso só acontece de ser que em 99,999% dos sistemas, que vai ser igual a 329 00:27:11,070 --> 00:27:15,800 ou um int ou um longo tempo. Depende apenas de 32-bit ou 64-bit. >> [Aluno] Okay. 330 00:27:15,800 --> 00:27:24,600 Em carros alegóricos, como é o ponto decimal designada em termos de bits? 331 00:27:24,600 --> 00:27:27,160 Como como binário? Sim >>. 332 00:27:27,160 --> 00:27:30,570 Você não precisa saber que para CS50. 333 00:27:30,570 --> 00:27:32,960 Você não precisa nem saber que em 61. 334 00:27:32,960 --> 00:27:37,350 Você não aprende que realmente em qualquer curso. 335 00:27:37,350 --> 00:27:42,740 É apenas uma representação. 336 00:27:42,740 --> 00:27:45,440 Eu esqueço os loteamentos bit exatas. 337 00:27:45,440 --> 00:27:53,380 A idéia de ponto flutuante é que você atribuir um número específico de bits para representar - 338 00:27:53,380 --> 00:27:56,550 Basicamente, tudo está em notação científica. 339 00:27:56,550 --> 00:28:05,600 Então você atribuir um número específico de bits para representar o número em si, como 1,2345. 340 00:28:05,600 --> 00:28:10,200 Eu nunca pode representar um número com mais dígitos do que 5. 341 00:28:12,200 --> 00:28:26,300 Então também atribuir um número específico de bits de modo que tende a ser semelhante 342 00:28:26,300 --> 00:28:32,810 você só pode ir até um certo número, que esse é o maior expoente você pode ter, 343 00:28:32,810 --> 00:28:36,190 e você só pode ir até um certo expoente, 344 00:28:36,190 --> 00:28:38,770 assim é o menor expoente você pode ter. 345 00:28:38,770 --> 00:28:44,410 >> Eu não me lembro os bits maneira exata são atribuídos a todos esses valores, 346 00:28:44,410 --> 00:28:47,940 mas um certo número de bits são dedicados a 1,2345, 347 00:28:47,940 --> 00:28:50,930 outro determinado número de bits são dedicados para o expoente, 348 00:28:50,930 --> 00:28:55,670 e só é possível para representar um expoente de um determinado tamanho. 349 00:28:55,670 --> 00:29:01,100 [Estudante] e um duplo? É que, como um flutuador extra longa? Sim >>. 350 00:29:01,100 --> 00:29:07,940 É a mesma coisa que um carro alegórico só que agora você está usando 8 bytes em vez de 4 bytes. 351 00:29:07,940 --> 00:29:11,960 Agora você vai ser capaz de usar 9 dígitos ou 10 dígitos, 352 00:29:11,960 --> 00:29:16,630 e isso vai ser capaz de ir até 300 em vez de 100. >> [Aluno] Okay. 353 00:29:16,630 --> 00:29:21,550 E flutua também são 4 bytes. Sim >>. 354 00:29:21,550 --> 00:29:27,520 Bem, mais uma vez, provavelmente depende global sobre a aplicação geral, 355 00:29:27,520 --> 00:29:30,610 mas flutuadores são 4 bytes, duplos são 8. 356 00:29:30,610 --> 00:29:33,440 Duplas são chamados de casal, porque eles são o dobro do tamanho dos carros alegóricos. 357 00:29:33,440 --> 00:29:38,380 [Aluno] Okay. E há dupla dobra? >> Não há. 358 00:29:38,380 --> 00:29:43,660 Eu acho - >> [estudante] Como longs longas? Sim >>. Acho que não. Sim. 359 00:29:43,660 --> 00:29:45,950 [Estudante] Em teste no ano passado, houve uma pergunta sobre a principal função 360 00:29:45,950 --> 00:29:49,490 ter que fazer parte do seu programa. 361 00:29:49,490 --> 00:29:52,310 A resposta foi que ele não tem que ser parte de seu programa. 362 00:29:52,310 --> 00:29:55,100 Em que situação? Isso é o que eu vi. 363 00:29:55,100 --> 00:29:59,090 [Bowden] Parece - >> [aluno] Que situação? 364 00:29:59,090 --> 00:30:02,880 Você tem o problema? >> [Aluno] Sim, eu definitivamente posso puxá-lo para cima. 365 00:30:02,880 --> 00:30:07,910 Ele não tem que ser, tecnicamente, mas basicamente vai ser. 366 00:30:07,910 --> 00:30:10,030 [Estudante] Eu vi um em um ano diferente. 367 00:30:10,030 --> 00:30:16,220 Era como Verdadeiro ou Falso: Um válido - >> Ah, um arquivo c.? 368 00:30:16,220 --> 00:30:18,790 . [Aluno] Qualquer arquivo deve ter c - [ambos falando de uma vez - ininteligível] 369 00:30:18,790 --> 00:30:21,120 Okay. Então, isso é separado. 370 00:30:21,120 --> 00:30:26,800 >> Uma. Arquivo c só precisa conter funções. 371 00:30:26,800 --> 00:30:32,400 Você pode compilar um arquivo em código de máquina, binário, qualquer que seja, 372 00:30:32,400 --> 00:30:36,620 sem que seja executável ainda. 373 00:30:36,620 --> 00:30:39,420 Um executável válido deve ter uma função principal. 374 00:30:39,420 --> 00:30:45,460 Você pode escrever 100 funções em um arquivo, mas não principais 375 00:30:45,460 --> 00:30:48,800 e depois compilar que até binário, 376 00:30:48,800 --> 00:30:54,460 então você escrever outro arquivo que tem apenas principal, mas chama um monte dessas funções 377 00:30:54,460 --> 00:30:56,720 neste arquivo binário por aqui. 378 00:30:56,720 --> 00:31:01,240 E assim, quando você está fazendo o executável, que é o que faz o linker 379 00:31:01,240 --> 00:31:05,960 é ele combina estes dois arquivos binários em um arquivo executável. 380 00:31:05,960 --> 00:31:11,400 Assim, um. Arquivo c não precisa ter uma função principal de todo. 381 00:31:11,400 --> 00:31:19,220 E em grandes bases de código você verá milhares de arquivos. C e 1 arquivo principal. 382 00:31:23,960 --> 00:31:26,110 Mais perguntas? 383 00:31:29,310 --> 00:31:31,940 [Aluno] Havia outra questão. 384 00:31:31,940 --> 00:31:36,710 Ele disse que fazer é um compilador. Verdadeiro ou Falso? 385 00:31:36,710 --> 00:31:42,030 E a resposta era falsa, e eu entendi por que ele não é como Clang. 386 00:31:42,030 --> 00:31:44,770 Mas o que nós chamamos de fazer, se não é? 387 00:31:44,770 --> 00:31:49,990 Fazer é, basicamente, apenas - Eu posso ver exatamente o que ele chama. 388 00:31:49,990 --> 00:31:52,410 Mas isso só executa comandos. 389 00:31:53,650 --> 00:31:55,650 Fazer. 390 00:31:58,240 --> 00:32:00,870 Posso puxar isso. Sim. 391 00:32:10,110 --> 00:32:13,180 Ah, sim. Faça também faz isso. 392 00:32:13,180 --> 00:32:17,170 Este diz que o propósito do utilitário make é determinar automaticamente 393 00:32:17,170 --> 00:32:19,610 que partes de um grande programa precisam ser recompilados 394 00:32:19,610 --> 00:32:22,350 e emitir os comandos para recompilá-los. 395 00:32:22,350 --> 00:32:27,690 Você pode fazer fazer arquivos que são absolutamente enorme. 396 00:32:27,690 --> 00:32:33,210 Faça olha as marcas de tempo de arquivos e, como dissemos antes, 397 00:32:33,210 --> 00:32:36,930 você pode compilar arquivos individuais para baixo, e não é até chegar ao linker 398 00:32:36,930 --> 00:32:39,270 que eles estão juntos em um executável. 399 00:32:39,270 --> 00:32:43,810 Então, se você tem 10 arquivos diferentes e você faz uma alteração em um deles, 400 00:32:43,810 --> 00:32:47,870 então o que fizer vai fazer é apenas recompilar que um arquivo 401 00:32:47,870 --> 00:32:50,640 e, depois, religar tudo juntos. 402 00:32:50,640 --> 00:32:53,020 Mas é muito mais burro do que isso. 403 00:32:53,020 --> 00:32:55,690 É até você para definir completamente que isso é o que deveria estar fazendo. 404 00:32:55,690 --> 00:32:59,560 É por padrão tem a capacidade de reconhecer essas coisas carimbo de tempo, 405 00:32:59,560 --> 00:33:03,220 mas você pode escrever um arquivo de make para fazer qualquer coisa. 406 00:33:03,220 --> 00:33:09,150 Você pode escrever um arquivo para fazer que quando você digita torná-lo apenas cd para outro diretório. 407 00:33:09,150 --> 00:33:15,560 Eu estava ficando frustrado, porque eu tudo rumo dentro da minha Appliance 408 00:33:15,560 --> 00:33:21,740 e depois eu ver o PDF do Mac. 409 00:33:21,740 --> 00:33:30,720 >> Então eu vou para Finder e que eu possa fazer Vai, Conectar ao Servidor, 410 00:33:30,720 --> 00:33:36,950 eo servidor de eu ligar para o meu aparelho e, em seguida, eu abrir o PDF 411 00:33:36,950 --> 00:33:40,190 que é compilado pelo LATEX. 412 00:33:40,190 --> 00:33:49,320 Mas eu estava ficando frustrado, porque cada vez que eu precisava atualizar o PDF, 413 00:33:49,320 --> 00:33:53,900 Eu tinha que copiá-lo para um diretório específico que poderia acessar 414 00:33:53,900 --> 00:33:57,710 e foi ficando chato. 415 00:33:57,710 --> 00:34:02,650 Então, em vez escrevi um arquivo make, que você tem que definir a forma como ele faz as coisas. 416 00:34:02,650 --> 00:34:06,130 Como você faz isso é em PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 Assim como qualquer outro arquivo de outra marca - ou eu acho que você ainda não viu os arquivos de fazer, 418 00:34:10,090 --> 00:34:13,510 mas temos no aparelho um arquivo de marca global que apenas diz: 419 00:34:13,510 --> 00:34:16,679 se você está compilando um arquivo C, utilize Clang. 420 00:34:16,679 --> 00:34:20,960 E aqui no meu arquivo make que eu faço eu digo, 421 00:34:20,960 --> 00:34:25,020 este arquivo que você vai querer compilar com LaTeX PDF. 422 00:34:25,020 --> 00:34:27,889 E por isso é LaTeX PDF que está fazendo a compilação. 423 00:34:27,889 --> 00:34:31,880 Fazer não é compilar. É só executar esses comandos na seqüência eu especifiquei. 424 00:34:31,880 --> 00:34:36,110 Por isso, corre LaTeX PDF, ele copia para o diretório que eu quero que ele seja copiado para, 425 00:34:36,110 --> 00:34:38,270 que cd para o diretório e faz outras coisas, 426 00:34:38,270 --> 00:34:42,380 mas tudo que faz é reconhecer quando um arquivo é modificado, 427 00:34:42,380 --> 00:34:45,489 e se muda, então ele vai executar os comandos que é suposto para executar 428 00:34:45,489 --> 00:34:48,760 quando as alterações do arquivo. >> [Aluno] Okay. 429 00:34:50,510 --> 00:34:54,420 Eu não sei de onde os arquivos fazem globais são para eu dar uma olhada. 430 00:34:57,210 --> 00:35:04,290 Outras perguntas? Qualquer coisa do passado quizzes? Quaisquer coisas ponteiro? 431 00:35:06,200 --> 00:35:08,730 Há coisas sutis com ponteiros como - 432 00:35:08,730 --> 00:35:10,220 Eu não vou ser capaz de encontrar a uma pergunta sobre ele - 433 00:35:10,220 --> 00:35:16,250 mas como este tipo de coisa. 434 00:35:19,680 --> 00:35:24,060 Certifique-se de entender que quando eu digo int * x * y - 435 00:35:24,890 --> 00:35:28,130 Este não é exatamente nada aqui, eu acho. 436 00:35:28,130 --> 00:35:32,140 Mas, como * x * y, aqueles são 2 variáveis ​​que estão na pilha. 437 00:35:32,140 --> 00:35:37,220 Quando eu digo que x = malloc (sizeof (int)), x ainda é uma variável na pilha, 438 00:35:37,220 --> 00:35:41,180 malloc é uma quadra no heap, e nós estamos tendo ponto x no heap. 439 00:35:41,180 --> 00:35:43,900 >> Então, alguma coisa sobre os pontos de pilha para o heap. 440 00:35:43,900 --> 00:35:48,100 Sempre que você malloc nada, você está inevitavelmente armazená-lo dentro de um ponteiro. 441 00:35:48,100 --> 00:35:55,940 Assim que o ponteiro estiver na pilha, o bloco é malloced na pilha. 442 00:35:55,940 --> 00:36:01,240 Muitas pessoas se confundem e dizem int * x = malloc; x é na pilha. 443 00:36:01,240 --> 00:36:04,100 Não. O que é x aponta para a pilha. 444 00:36:04,100 --> 00:36:08,540 x si é na pilha, a não ser que, por qualquer razão, você x ser uma variável global, 445 00:36:08,540 --> 00:36:11,960 caso em que passa a ser em outra região de memória. 446 00:36:13,450 --> 00:36:20,820 Então, manter o controle, estes diagramas de caixa e flecha são bastante comuns para o quiz. 447 00:36:20,820 --> 00:36:25,740 Ou se não é no teste 0, ele estará no questionário 1. 448 00:36:27,570 --> 00:36:31,940 Você deve saber tudo isso, os passos na compilação 449 00:36:31,940 --> 00:36:35,740 desde que você teve que responder a perguntas sobre aqueles. Sim. 450 00:36:35,740 --> 00:36:38,940 [Aluno] Podemos ir mais dessas etapas - >> Claro. 451 00:36:48,340 --> 00:36:58,640 Antes de passos e compilação temos o pré-processamento, 452 00:36:58,640 --> 00:37:16,750 compilação, montagem e ligação. 453 00:37:16,750 --> 00:37:21,480 Pré-processamento. O que isso faz? 454 00:37:29,720 --> 00:37:32,290 É o passo mais fácil em - bem, não como - 455 00:37:32,290 --> 00:37:35,770 isso não significa que deveria ser óbvio, mas é o passo mais fácil. 456 00:37:35,770 --> 00:37:38,410 Vocês poderiam implementá-lo vocês mesmos. Sim. 457 00:37:38,410 --> 00:37:43,410 [Aluno] Pegue o que você tem em seu inclui como este e ele copia e depois também define. 458 00:37:43,410 --> 00:37:49,250 Ele procura por coisas como # include e # define, 459 00:37:49,250 --> 00:37:53,800 e apenas copia e cola o que aqueles realmente significam. 460 00:37:53,800 --> 00:37:59,240 Então, quando você diz # include cs50.h, o pré-processador está copiando e colando cs50.h 461 00:37:59,240 --> 00:38:01,030 em que a linha. 462 00:38:01,030 --> 00:38:06,640 Quando você diz # define x para ser 4, o pré-processador passa por todo o programa 463 00:38:06,640 --> 00:38:10,400 e substitui todas as ocorrências de x por 4. 464 00:38:10,400 --> 00:38:17,530 Assim, o pré-processador tem um arquivo C válido e gera um arquivo válido C 465 00:38:17,530 --> 00:38:20,300 onde as coisas têm sido copiado e colado. 466 00:38:20,300 --> 00:38:24,230 Então agora compilar. O que isso faz? 467 00:38:25,940 --> 00:38:28,210 [Aluno] Ele vai de C para binário. 468 00:38:28,210 --> 00:38:30,970 >> [Bowden] Não percorrer todo o caminho para binário. 469 00:38:30,970 --> 00:38:34,220 [Estudante] para código de máquina, então? >> Não é código de máquina. 470 00:38:34,220 --> 00:38:35,700 [Aluno] Assembléia? >> Assembleia. 471 00:38:35,700 --> 00:38:38,890 Ele vai para a Assembléia antes que vá todo o caminho para o código C, 472 00:38:38,890 --> 00:38:45,010 ea maioria das línguas fazer algo assim. 473 00:38:47,740 --> 00:38:50,590 Escolha qualquer linguagem de alto nível, e se você estiver indo para compilá-lo, 474 00:38:50,590 --> 00:38:52,390 é provável que compilar em etapas. 475 00:38:52,390 --> 00:38:58,140 Primeiro ele vai compilar o Python para C, então ele vai para compilar C a Assembléia, 476 00:38:58,140 --> 00:39:01,600 e Assembléia vai ficar traduzido para binário. 477 00:39:01,600 --> 00:39:07,800 Então compilação vai trazê-lo de C para Assembly. 478 00:39:07,800 --> 00:39:12,130 A palavra compilando normalmente significa trazê-lo a partir de um nível mais elevado 479 00:39:12,130 --> 00:39:14,340 a um menor nível de linguagem de programação. 480 00:39:14,340 --> 00:39:19,190 Portanto, esta é a única etapa na compilação onde você começa com uma linguagem de alto nível 481 00:39:19,190 --> 00:39:23,270 e acabam em uma linguagem de baixo nível, e é por isso que a etapa é chamado de compilação. 482 00:39:25,280 --> 00:39:33,370 [Aluno] Durante a compilação, vamos dizer que você fez # include cs50.h. 483 00:39:33,370 --> 00:39:42,190 Será que o compilador recompilar o cs50.h, como as funções que estão lá, 484 00:39:42,190 --> 00:39:45,280 e traduzir isso em código Assembléia, bem como, 485 00:39:45,280 --> 00:39:50,830 ou vai copiar e colar algo que tem sido pré-montagem? 486 00:39:50,830 --> 00:39:56,910 cs50.h vai praticamente nunca acabar na Assembleia. 487 00:39:59,740 --> 00:40:03,680 Coisas como protótipos de função e as coisas são apenas para você ter cuidado. 488 00:40:03,680 --> 00:40:09,270 Ele garante que o compilador pode verificar as coisas que você está chamando funções 489 00:40:09,270 --> 00:40:12,910 com os tipos de retorno de direita e os argumentos certos e outras coisas. 490 00:40:12,910 --> 00:40:18,350 >> Então cs50.h serão pré-processados ​​no arquivo, e então quando ele está compilando 491 00:40:18,350 --> 00:40:22,310 é basicamente jogado fora depois que ele garante que tudo está sendo chamado corretamente. 492 00:40:22,310 --> 00:40:29,410 Mas as funções definidas na biblioteca CS50, que são separados cs50.h, 493 00:40:29,410 --> 00:40:33,610 aqueles que não será compilado separadamente. 494 00:40:33,610 --> 00:40:37,270 Que realmente vai vir para baixo na etapa de ligação, assim que nós vamos chegar a isso em um segundo. 495 00:40:37,270 --> 00:40:40,100 Mas, primeiro, o que é montagem? 496 00:40:41,850 --> 00:40:44,500 [Estudante] Assembleia para binário? Sim >>. 497 00:40:46,300 --> 00:40:48,190 Montagem. 498 00:40:48,190 --> 00:40:54,710 Nós não chamá-lo de compilação porque Assembléia é praticamente uma tradução pura de binário. 499 00:40:54,710 --> 00:41:00,230 Há uma lógica muito pouco em ir de Assembléia para binário. 500 00:41:00,230 --> 00:41:03,180 É como olhar para cima na tabela, oh, nós temos essa instrução; 501 00:41:03,180 --> 00:41:06,290 que corresponde ao binário 01110. 502 00:41:10,200 --> 00:41:15,230 E assim os arquivos que a montagem geralmente saídas são. Arquivos o. 503 00:41:15,230 --> 00:41:19,020 E arquivos. O são o que estávamos dizendo antes, 504 00:41:19,020 --> 00:41:21,570 como um arquivo não precisa ter uma função principal. 505 00:41:21,570 --> 00:41:27,640 Qualquer arquivo pode ser compilado para baixo para um arquivo o. Enquanto ele é um arquivo C válido. 506 00:41:27,640 --> 00:41:30,300 Ele pode ser compilado para baixo. O. 507 00:41:30,300 --> 00:41:43,030 Agora, ligando é o que realmente traz um monte de. O arquivos e os leva para um executável. 508 00:41:43,030 --> 00:41:51,110 E então o que faz é que liga você pode pensar a biblioteca como um arquivo CS50 o.. 509 00:41:51,110 --> 00:41:56,980 É um arquivo binário já compilado. 510 00:41:56,980 --> 00:42:03,530 E assim, quando você compilar seu arquivo, seu hello.c, que chama GetString, 511 00:42:03,530 --> 00:42:06,360 hello.c é compilado até hello.o, 512 00:42:06,360 --> 00:42:08,910 hello.o está agora em binário. 513 00:42:08,910 --> 00:42:12,830 Ele usa GetString, por isso precisa ir para cs50.o, 514 00:42:12,830 --> 00:42:16,390 eo vinculador smooshes-los juntos e copia GetString para este arquivo 515 00:42:16,390 --> 00:42:20,640 e sai com um executável que tem todas as funções que necessita. 516 00:42:20,640 --> 00:42:32,620 Então cs50.o não é realmente um arquivo de O, mas está perto o suficiente para que não há diferença fundamental. 517 00:42:32,620 --> 00:42:36,880 Então, ligando apenas traz um monte de arquivos juntos 518 00:42:36,880 --> 00:42:41,390 que separadamente conter todas as funções que preciso utilizar 519 00:42:41,390 --> 00:42:46,120 e cria o executável que vai realmente funcionar. 520 00:42:48,420 --> 00:42:50,780 >> E por isso é também o que dizíamos antes 521 00:42:50,780 --> 00:42:55,970 onde você pode ter 1000. arquivos C, compilá-los todos. arquivos Ô, 522 00:42:55,970 --> 00:43:00,040 que provavelmente vai demorar um pouco, então você alterar uma. arquivo c. 523 00:43:00,040 --> 00:43:05,480 Você só precisa recompilar que 1. Arquivo c e depois ligar novamente tudo o mais, 524 00:43:05,480 --> 00:43:07,690 vincular tudo de volta juntos. 525 00:43:09,580 --> 00:43:11,430 [Aluno] Quando estamos ligando escrevemos lcs50? 526 00:43:11,430 --> 00:43:20,510 Sim, assim lcs50. Que os sinais de bandeira para o vinculador que você deve estar ligando nessa biblioteca. 527 00:43:26,680 --> 00:43:28,910 Perguntas? 528 00:43:41,310 --> 00:43:46,860 Temos ido mais binário diferente que 5 segundos em primeira palestra? 529 00:43:50,130 --> 00:43:53,010 Acho que não. 530 00:43:55,530 --> 00:43:58,820 Você deve saber tudo do SO grande que já sabemos, 531 00:43:58,820 --> 00:44:02,670 e você deve ser capaz de, se lhe deu uma função, 532 00:44:02,670 --> 00:44:09,410 você deve ser capaz de dizer que é grande O, aproximadamente. Ou bem grande, ó é áspera. 533 00:44:09,410 --> 00:44:15,300 Então, se você ver aninhados loops looping sobre o mesmo número de coisas, 534 00:44:15,300 --> 00:44:22,260 como int i, i > [aluno] n ao quadrado. >> Tende a ser n ao quadrado. 535 00:44:22,260 --> 00:44:25,280 Se você triplo aninhados, ele tende a ser n cubos. 536 00:44:25,280 --> 00:44:29,330 Então, que tipo de coisa você deve ser capaz de apontar imediatamente. 537 00:44:29,330 --> 00:44:33,890 Você precisa saber o tipo de inserção e bubble sort e merge sort e de todos aqueles. 538 00:44:33,890 --> 00:44:41,420 É mais fácil entender por que eles são aqueles n ao quadrado e n log n e tudo isso 539 00:44:41,420 --> 00:44:47,810 porque eu acho que houve um quiz em um ano em que, basicamente, deu-lhe 540 00:44:47,810 --> 00:44:55,050 uma implementação do bubble sort, e disse: "O que é o tempo de execução desta função?" 541 00:44:55,050 --> 00:45:01,020 Então, se você reconhecê-lo como uma espécie de bolha, então você pode dizer imediatamente n ao quadrado. 542 00:45:01,020 --> 00:45:05,470 Mas se você olhar para ele, você não precisa mesmo de perceber que é uma espécie de bolha; 543 00:45:05,470 --> 00:45:08,990 você pode apenas dizer que este está fazendo isso e isso. Este é n ao quadrado. 544 00:45:12,350 --> 00:45:14,710 [Aluno] Há exemplos difíceis que você pode vir acima com, 545 00:45:14,710 --> 00:45:20,370 como uma idéia semelhante de descobrir? 546 00:45:20,370 --> 00:45:24,450 >> Eu não acho que iria dar-lhe alguns exemplos difíceis. 547 00:45:24,450 --> 00:45:30,180 O bubble sort é tão resistente quanto íamos nós, 548 00:45:30,180 --> 00:45:36,280 e mesmo que, desde que você entenda que você está interagindo sobre a matriz 549 00:45:36,280 --> 00:45:41,670 para cada elemento da matriz, o que vai ser algo que n ao quadrado. 550 00:45:45,370 --> 00:45:49,940 Há questões gerais, como aqui nós temos - Ah. 551 00:45:55,290 --> 00:45:58,530 Ainda no outro dia, Doug afirmou: "Eu inventei um algoritmo que pode classificar um array 552 00:45:58,530 --> 00:46:01,780 "De n números em O (log n) o tempo!" 553 00:46:01,780 --> 00:46:04,900 Assim como sabemos que isso é impossível? 554 00:46:04,900 --> 00:46:08,850 [Resposta do aluno inaudível] >> Yeah. 555 00:46:08,850 --> 00:46:13,710 No mínimo, você tem que tocar cada elemento na matriz, 556 00:46:13,710 --> 00:46:16,210 por isso é impossível de classificar uma matriz de - 557 00:46:16,210 --> 00:46:20,850 Se tudo estiver em ordem não separado, então você vai estar tocando tudo na matriz, 558 00:46:20,850 --> 00:46:25,320 por isso é impossível fazê-lo em menos de O de n. 559 00:46:27,430 --> 00:46:30,340 [Aluno] Você nos mostrou que o exemplo de ser capaz de fazê-lo em O de n 560 00:46:30,340 --> 00:46:33,920 se você usar um monte de memória. Sim >>. 561 00:46:33,920 --> 00:46:37,970 E isso é - eu esqueço o que isso é - É contando tipo? 562 00:46:47,360 --> 00:46:51,330 Hmm. Que é um algoritmo de ordenação inteiro. 563 00:46:59,850 --> 00:47:05,100 Eu estava olhando para o nome especial para isso que eu não conseguia me lembrar, na semana passada. 564 00:47:05,100 --> 00:47:13,000 Sim. Estes são os tipos de tipos que podem realizar as coisas em grande O de n. 565 00:47:13,000 --> 00:47:18,430 Mas há limitações, como você só pode usar números inteiros até um determinado número. 566 00:47:20,870 --> 00:47:24,560 Além disso, se você está tentando classificar Sim. Aí algo - 567 00:47:24,560 --> 00:47:30,750 Se a sua matriz é 012, -12, 151, 4 milhões, 568 00:47:30,750 --> 00:47:35,120 em seguida, o elemento único vai arruinar completamente a triagem inteiro. 569 00:47:42,060 --> 00:47:44,030 >> Perguntas? 570 00:47:49,480 --> 00:47:58,870 [Aluno] Se você tem uma função recursiva e isso só faz as chamadas recursivas 571 00:47:58,870 --> 00:48:02,230 dentro de uma instrução de retorno, que é rabo recursiva, 572 00:48:02,230 --> 00:48:07,360 e assim que não iria usar mais memória durante o tempo de execução 573 00:48:07,360 --> 00:48:12,550 ou seria, pelo menos, usar a memória comparável como solução iterativa? 574 00:48:12,550 --> 00:48:14,530 [Bowden] Sim. 575 00:48:14,530 --> 00:48:19,840 Provavelmente seria um pouco mais lento, mas não realmente. 576 00:48:19,840 --> 00:48:23,290 Cauda recursiva é muito bom. 577 00:48:23,290 --> 00:48:32,640 Olhando novamente para quadros de pilha, vamos dizer que temos principal 578 00:48:32,640 --> 00:48:42,920 e temos barra int (int x) ou algo assim. 579 00:48:42,920 --> 00:48:52,310 Esta não é uma função recursiva perfeito, mas barra de retorno (x - 1). 580 00:48:52,310 --> 00:48:57,620 Então, obviamente, este é falho. Você precisa casos base e outras coisas. 581 00:48:57,620 --> 00:49:00,360 Mas a idéia aqui é que esta é a cauda recursiva, 582 00:49:00,360 --> 00:49:06,020 o que significa que quando a barra de chamadas principal que vai ter o seu quadro de pilha. 583 00:49:09,550 --> 00:49:12,440 Neste quadro de pilha lá vai ser um pequeno bloco de memória 584 00:49:12,440 --> 00:49:17,490 que corresponde ao seu argumento x. 585 00:49:17,490 --> 00:49:25,840 E assim vamos dizer principal acontece a chamar bar (100); 586 00:49:25,840 --> 00:49:30,050 Então x vai começar como 100. 587 00:49:30,050 --> 00:49:35,660 Se o compilador reconhece que esta é uma função recursiva cauda, 588 00:49:35,660 --> 00:49:38,540 em seguida, quando a barra faz a sua chamada recursiva para barrar, 589 00:49:38,540 --> 00:49:45,490 em vez de fazer um novo quadro de pilha, que é onde a pilha começa a crescer em grande parte, 590 00:49:45,490 --> 00:49:48,220 eventualmente, ele será executado na pilha e então você começa segfaults 591 00:49:48,220 --> 00:49:51,590 porque a memória começa a colidir. 592 00:49:51,590 --> 00:49:54,830 >> Então, em vez de fazer o seu próprio quadro de pilha, pode realizar, 593 00:49:54,830 --> 00:49:59,080 Ei, eu nunca realmente precisa para voltar a este quadro de pilha, 594 00:49:59,080 --> 00:50:08,040 assim, em vez vou substituir esse argumento com 99 e, em seguida, começar a barra de todo. 595 00:50:08,040 --> 00:50:11,810 E então ele vai fazer isso de novo e vai chegar barra de retorno (x - 1), 596 00:50:11,810 --> 00:50:17,320 e em vez de fazer um novo quadro de pilha, ele vai apenas substituir seu argumento atual com 98 597 00:50:17,320 --> 00:50:20,740 e depois saltar de volta para o início do bar. 598 00:50:23,860 --> 00:50:30,430 Essas operações, substituindo esse valor 1 na pilha e saltar de volta para o início, 599 00:50:30,430 --> 00:50:32,430 são bastante eficientes. 600 00:50:32,430 --> 00:50:41,500 Portanto, não é apenas o uso de memória mesmo que uma função própria, que é iterativo 601 00:50:41,500 --> 00:50:45,390 porque você está usando apenas um quadro de pilha, mas você não está sofrendo as desvantagens 602 00:50:45,390 --> 00:50:47,240 de ter que chamar funções. 603 00:50:47,240 --> 00:50:50,240 Funções de chamada pode ser um pouco caro porque tem que fazer toda essa configuração 604 00:50:50,240 --> 00:50:52,470 e desmontagem e todas essas coisas. 605 00:50:52,470 --> 00:50:58,160 Portanto, este recursão de cauda é bom. 606 00:50:58,160 --> 00:51:01,170 [Aluno] Por que não criar novos passos? 607 00:51:01,170 --> 00:51:02,980 Porque ele percebe que não precisa. 608 00:51:02,980 --> 00:51:07,800 A chamada para a barra está apenas retornando a chamada recursiva. 609 00:51:07,800 --> 00:51:12,220 Por isso, não precisa de fazer qualquer coisa com o valor de retorno. 610 00:51:12,220 --> 00:51:15,120 Ele só vai imediatamente devolvê-lo. 611 00:51:15,120 --> 00:51:20,530 Por isso, só vai substituir o seu próprio argumento e começar de novo. 612 00:51:20,530 --> 00:51:25,780 E também, se você não tem a versão cauda recursiva, 613 00:51:25,780 --> 00:51:31,460 então você obter todos estes bares onde, quando esta barra retorna 614 00:51:31,460 --> 00:51:36,010 ele tem que retornar o seu valor para este, em seguida, que a barra retorna imediatamente 615 00:51:36,010 --> 00:51:39,620 e retorna o seu valor para este, em seguida, é só ir para retornar imediatamente 616 00:51:39,620 --> 00:51:41,350 e retornar o seu valor a este. 617 00:51:41,350 --> 00:51:45,350 Então você está salvando esta aparecendo todas essas coisas fora da pilha 618 00:51:45,350 --> 00:51:48,730 uma vez que o valor de retorno é apenas vai ser passado por todo o caminho de volta de qualquer maneira. 619 00:51:48,730 --> 00:51:55,400 Então por que não substituir o nosso argumento com o argumento atualizado e começar de novo? 620 00:51:57,460 --> 00:52:01,150 Se a função não é recursiva cauda, ​​se você faz algo como - 621 00:52:01,150 --> 00:52:07,530 [Aluno] se bar (x + 1). Sim >>. 622 00:52:07,530 --> 00:52:11,770 >> Então, se você colocá-lo em condições, então você está fazendo algo com o valor de retorno. 623 00:52:11,770 --> 00:52:16,260 Ou mesmo se você acabou de fazer return 2 * bar (x - 1). 624 00:52:16,260 --> 00:52:23,560 Então bar agora (x - 1) precisa voltar para que ele para calcular 2 vezes esse valor, 625 00:52:23,560 --> 00:52:26,140 então agora é necessário seu quadro de pilha separada, 626 00:52:26,140 --> 00:52:31,180 e agora, não importa o quão duro você tente, você vai precisar de - 627 00:52:31,180 --> 00:52:34,410 Esta não é a cauda recursiva. 628 00:52:34,410 --> 00:52:37,590 [Aluno] Será que eu tento trazer uma recursão a apontar para uma recursão de cauda - 629 00:52:37,590 --> 00:52:41,450 [Bowden] Em um mundo ideal, mas na CS50 você não precisa fazer isso. 630 00:52:43,780 --> 00:52:49,280 A fim de obter recursão de cauda, ​​geralmente, você configura um argumento adicional 631 00:52:49,280 --> 00:52:53,550 onde bar terá int x em y 632 00:52:53,550 --> 00:52:56,990 e y corresponde à última coisa que você quer voltar. 633 00:52:56,990 --> 00:53:03,650 Então esta você vai estar retornando bar (x - 1), 2 * y. 634 00:53:03,650 --> 00:53:09,810 Então, isso é apenas um alto nível como você transformar as coisas para ser cauda recursiva. 635 00:53:09,810 --> 00:53:13,790 Mas o argumento extra - 636 00:53:13,790 --> 00:53:17,410 E então, no final, quando você chegar ao seu caso base, você acabou de voltar y 637 00:53:17,410 --> 00:53:22,740 porque você foi acumulando o tempo todo o valor de retorno que você deseja. 638 00:53:22,740 --> 00:53:27,280 Você meio que tem feito de forma iterativa, mas através de chamadas recursivas. 639 00:53:32,510 --> 00:53:34,900 Perguntas? 640 00:53:34,900 --> 00:53:39,890 [Estudante] Talvez sobre a aritmética de ponteiro, como quando se usa cordas. >> Claro. 641 00:53:39,890 --> 00:53:43,610 Aritmética de ponteiro. 642 00:53:43,610 --> 00:53:48,440 Ao utilizar cordas é fácil porque as cordas são estrelas char, 643 00:53:48,440 --> 00:53:51,860 chars são para sempre e sempre um único byte, 644 00:53:51,860 --> 00:53:57,540 e assim a aritmética de ponteiro é equivalente a aritmética regular, quando você está lidando com cordas. 645 00:53:57,540 --> 00:54:08,790 Vamos apenas dizer que char * s = "Olá". 646 00:54:08,790 --> 00:54:11,430 Portanto, temos um bloco na memória. 647 00:54:19,490 --> 00:54:22,380 Ele precisa de 6 bytes, porque você sempre precisa do terminador nulo. 648 00:54:22,380 --> 00:54:28,620 E char * s vai para apontar para o início desta matriz. 649 00:54:28,620 --> 00:54:32,830 Assim s aponte lá. 650 00:54:32,830 --> 00:54:36,710 Agora, isso é basicamente como qualquer matriz funciona, 651 00:54:36,710 --> 00:54:40,780 independentemente de ele era um retorno por malloc ou se é a pilha. 652 00:54:40,780 --> 00:54:47,110 Qualquer matriz é, basicamente, um ponteiro para o início da matriz, 653 00:54:47,110 --> 00:54:53,640 e depois de qualquer operação de matriz, qualquer indexação, é só ir em que a matriz de um determinado deslocamento. 654 00:54:53,640 --> 00:55:05,360 >> Portanto, quando digo algo como s [3], o que vai s e contando 3 caracteres dentro 655 00:55:05,360 --> 00:55:12,490 Assim, s [3], temos 0, 1, 2, 3, de modo s [3] vai para se referir a este l. 656 00:55:12,490 --> 00:55:20,460 [Aluno] E nós poderíamos chegar ao mesmo valor, fazendo s + 3 e estrela parênteses? 657 00:55:20,460 --> 00:55:22,570 Sim. 658 00:55:22,570 --> 00:55:26,010 Isto é equivalente a * (s + 3); 659 00:55:26,010 --> 00:55:31,240 e que é para sempre e sempre equivalentes, não importa o que você faz. 660 00:55:31,240 --> 00:55:34,070 Você nunca precisa usar a sintaxe de suporte. 661 00:55:34,070 --> 00:55:37,770 Você sempre pode usar o * (s + 3) sintaxe. 662 00:55:37,770 --> 00:55:40,180 As pessoas tendem a gostar da sintaxe suporte, no entanto. 663 00:55:40,180 --> 00:55:43,860 [Aluno] Então, todas as matrizes são na verdade apenas ponteiros. 664 00:55:43,860 --> 00:55:53,630 Há uma ligeira distinção quando digo int x [4]; >> [aluno] Será que criar a memória? 665 00:55:53,630 --> 00:56:03,320 [Bowden] Isso vai criar 4 ints na pilha, de modo geral 16 bytes. 666 00:56:03,320 --> 00:56:05,700 Vai criar 16 bytes na pilha. 667 00:56:05,700 --> 00:56:09,190 x não é armazenada em qualquer lugar. 668 00:56:09,190 --> 00:56:13,420 É apenas um símbolo referente ao início da coisa. 669 00:56:13,420 --> 00:56:17,680 Porque você declarou a matriz dentro da função, 670 00:56:17,680 --> 00:56:22,340 o que o compilador vai fazer é substituir todas as ocorrências da variável x 671 00:56:22,340 --> 00:56:26,400 com o local onde aconteceu a escolha de colocar estes 16 bytes. 672 00:56:26,400 --> 00:56:30,040 Ele não pode fazer isso com char * s porque s é um ponteiro real. 673 00:56:30,040 --> 00:56:32,380 Ela é livre para, em seguida, apontar para outras coisas. 674 00:56:32,380 --> 00:56:36,140 x é uma constante. Você não pode se apontar para uma matriz diferente. >> [Aluno] Okay. 675 00:56:36,140 --> 00:56:43,420 Mas esta idéia, esta indexação, é o mesmo, independentemente de se tratar de uma matriz tradicional 676 00:56:43,420 --> 00:56:48,230 ou se é um ponteiro para alguma coisa ou se é um ponteiro para uma matriz malloced. 677 00:56:48,230 --> 00:56:59,770 E, na verdade, é assim equivalente que essa é também a mesma coisa. 678 00:56:59,770 --> 00:57:05,440 Ele realmente apenas traduz o que está dentro dos colchetes eo que sobrou dos suportes, 679 00:57:05,440 --> 00:57:07,970 adiciona-los juntos, e dereferences. 680 00:57:07,970 --> 00:57:14,710 Portanto, esta é tão válida quanto * (s + 3) ou s [3]. 681 00:57:16,210 --> 00:57:22,090 [Estudante] Você pode ter ponteiros apontam para 2-dimensional arrays? 682 00:57:22,090 --> 00:57:27,380 >> É mais difícil. Tradicionalmente, no. 683 00:57:27,380 --> 00:57:34,720 Uma matriz de 2 dimensões é apenas uma matriz 1-dimensional com alguma sintaxe conveniente 684 00:57:34,720 --> 00:57:54,110 porque quando eu digo int x [3] [3], isso é realmente apenas uma matriz com 9 valores. 685 00:57:55,500 --> 00:58:03,000 E então quando eu índice, o compilador sabe o que quero dizer. 686 00:58:03,000 --> 00:58:13,090 Se eu disser x [1] [2], ele sabe que eu quero ir para a segunda linha, por isso vai pular o primeiro 3, 687 00:58:13,090 --> 00:58:17,460 e então ele quer que a segunda coisa em que, por isso vai receber um presente. 688 00:58:17,460 --> 00:58:20,480 Mas ainda é apenas uma matriz unidimensional. 689 00:58:20,480 --> 00:58:23,660 E assim se eu queria atribuir um ponteiro para essa matriz, 690 00:58:23,660 --> 00:58:29,770 Eu diria int * p = x; 691 00:58:29,770 --> 00:58:33,220 O tipo de x é apenas - 692 00:58:33,220 --> 00:58:38,280 É tipo dizendo aproximada de x, uma vez que é apenas um símbolo e não é uma variável real, 693 00:58:38,280 --> 00:58:40,140 mas é apenas um int *. 694 00:58:40,140 --> 00:58:44,840 x é apenas um ponteiro para o início desta. >> [Aluno] Okay. 695 00:58:44,840 --> 00:58:52,560 E por isso não vou ser capaz de acessar [1] [2]. 696 00:58:52,560 --> 00:58:58,370 Eu acho que existe uma sintaxe especial para declarar um ponteiro, 697 00:58:58,370 --> 00:59:12,480 algo ridículo como int (* p [-. algo absolutamente ridículo que eu não sei mesmo. 698 00:59:12,480 --> 00:59:17,090 Mas há uma sintaxe para declarar ponteiros como com parênteses e coisas. 699 00:59:17,090 --> 00:59:22,960 Pode até não deixar você fazer isso. 700 00:59:22,960 --> 00:59:26,640 Eu poderia olhar para trás, algo que me diga a verdade. 701 00:59:26,640 --> 00:59:34,160 Vou procurá-lo mais tarde, se houver uma sintaxe para ponto. Mas você nunca vai vê-lo. 702 00:59:34,160 --> 00:59:39,670 E mesmo a sintaxe é tão arcaico que se você usá-lo, as pessoas vão se perplexo. 703 00:59:39,670 --> 00:59:43,540 Matrizes multidimensionais são muito raros como ela é. 704 00:59:43,540 --> 00:59:44,630 Está muito bonito - 705 00:59:44,630 --> 00:59:48,490 Bem, se você está fazendo as coisas da matriz não vai ser raro, 706 00:59:48,490 --> 00:59:56,730 mas em C você raramente vai usar matrizes multidimensionais. 707 00:59:57,630 --> 01:00:00,470 Sim. >> [Aluno] Digamos que você tem uma matriz muito longo. 708 01:00:00,470 --> 01:00:03,900 >> Assim, na memória virtual parece ser todos consecutivos, 709 01:00:03,900 --> 01:00:05,640 como os elementos ao lado uns dos outros, 710 01:00:05,640 --> 01:00:08,770 mas na memória física, seria possível para que isso se separaram? Sim >>. 711 01:00:08,770 --> 01:00:16,860 Como a memória funciona virtuais é apenas separa - 712 01:00:19,220 --> 01:00:24,860 A unidade de distribuição é uma página, que tende a ser de 4 kilobytes, 713 01:00:24,860 --> 01:00:29,680 e assim, quando um processo diz, hey, eu quero usar essa memória, 714 01:00:29,680 --> 01:00:35,970 o sistema operacional vai atribuir-lhe 4 kilobytes para esse pequeno bloco de memória. 715 01:00:35,970 --> 01:00:39,100 Mesmo se você usar apenas um único byte pouco em todo o bloco de memória, 716 01:00:39,100 --> 01:00:42,850 o sistema operacional vai dar o total de 4 kilobytes. 717 01:00:42,850 --> 01:00:49,410 Então, o que isto significa é que eu poderia ter - digamos que esta é a minha pilha. 718 01:00:49,410 --> 01:00:53,180 Esta pilha podiam ser separados. Minha pilha poderia ser megabytes e megabytes. 719 01:00:53,180 --> 01:00:55,020 Minha pilha pode ser enorme. 720 01:00:55,020 --> 01:01:00,220 Mas a pilha em si tem de ser dividido em páginas individuais, 721 01:01:00,220 --> 01:01:09,010 que, se olharmos para cá, digamos que esta é a nossa memória RAM, 722 01:01:09,010 --> 01:01:16,600 se eu tiver 2 gigabytes de memória RAM, este é o endereço real 0 como o byte 0 da minha memória RAM, 723 01:01:16,600 --> 01:01:22,210 e este é de 2 gigabytes todo o caminho até aqui. 724 01:01:22,210 --> 01:01:27,230 Portanto, esta página pode corresponder a este bloco aqui. 725 01:01:27,230 --> 01:01:29,400 Esta página pode corresponder a este bloco aqui. 726 01:01:29,400 --> 01:01:31,560 Este pode corresponder a este aqui. 727 01:01:31,560 --> 01:01:35,540 Assim, o sistema operacional é livre para atribuir memória física 728 01:01:35,540 --> 01:01:39,320 para qualquer página individual arbitrariamente. 729 01:01:39,320 --> 01:01:46,180 E isso significa que, se isso acontece fronteira para straddle uma matriz, 730 01:01:46,180 --> 01:01:50,070 uma matriz passa a ser deixada deste e direita da ordem de uma página, 731 01:01:50,070 --> 01:01:54,460 em seguida, que a matriz vai ser dividida em memória física. 732 01:01:54,460 --> 01:01:59,280 E então quando você sair do programa, ao final do processo, 733 01:01:59,280 --> 01:02:05,690 esses mapeamentos obter apagados e então é livre para usar estes pequenos blocos para outras coisas. 734 01:02:14,730 --> 01:02:17,410 Mais perguntas? 735 01:02:17,410 --> 01:02:19,960 [Aluno] aritmética O ponteiro. >> Oh yeah. 736 01:02:19,960 --> 01:02:28,410 Cordas foram mais fáceis, mas olhando para algo como ints, 737 01:02:28,410 --> 01:02:35,000 Então, de volta para int x [4]; 738 01:02:35,000 --> 01:02:41,810 Se isto é uma matriz ou se é um ponteiro para uma matriz malloced de 4 números inteiros, 739 01:02:41,810 --> 01:02:47,060 ele vai ser tratado da mesma maneira. 740 01:02:50,590 --> 01:02:53,340 [Estudante] Então matrizes são na pilha? 741 01:03:01,400 --> 01:03:05,270 [Bowden] Matrizes não são na pilha. >> [Aluno] Oh. 742 01:03:05,270 --> 01:03:08,320 >> [Bowden] Este tipo de arranjo tende a ser na pilha 743 01:03:08,320 --> 01:03:12,220 a menos que você declarou na - ignorando variáveis ​​globais. Não use variáveis ​​globais. 744 01:03:12,220 --> 01:03:16,280 Dentro de uma função que eu digo int x [4]; 745 01:03:16,280 --> 01:03:22,520 Vai criar um bloco de 4 inteiro na pilha para esta matriz. 746 01:03:22,520 --> 01:03:26,960 Mas este malloc (4 * sizeof (int)); está a ir na pilha. 747 01:03:26,960 --> 01:03:31,870 Mas após este ponto eu posso usar x e p em praticamente da mesma forma, 748 01:03:31,870 --> 01:03:36,140 Para além das excepções que eu disse antes sobre você pode reatribuir p. 749 01:03:36,140 --> 01:03:40,960 Tecnicamente, as suas dimensões são um pouco diferentes, mas isso é completamente irrelevante. 750 01:03:40,960 --> 01:03:43,310 Você nunca realmente usar seus tamanhos. 751 01:03:48,020 --> 01:03:56,810 O que eu poderia dizer p p [3] = 2; ou x [3] = 2; 752 01:03:56,810 --> 01:03:59,680 Você pode usá-los em exatamente da mesma maneira. 753 01:03:59,680 --> 01:04:01,570 Assim, a aritmética de ponteiro agora - Sim. 754 01:04:01,570 --> 01:04:07,390 [Aluno] Você não tem que fazer p * se você tem os suportes? 755 01:04:07,390 --> 01:04:11,720 Os suportes são uma dereference implícita. Ok >>. 756 01:04:11,720 --> 01:04:20,200 Na verdade, também o que você está dizendo com o que você pode obter matrizes multidimensionais 757 01:04:20,200 --> 01:05:02,650 com ponteiros, o que você pode fazer é algo como, digamos, int ** pp = malloc (sizeof (int *) * 5); 758 01:05:02,650 --> 01:05:06,900 Eu só vou escrever tudo primeiro. 759 01:05:37,880 --> 01:05:41,020 Eu não queria isso. 760 01:05:41,020 --> 01:05:42,550 Okay. 761 01:05:42,550 --> 01:05:48,910 O que eu fiz aqui é - Isso deve ser pp [i]. 762 01:05:48,910 --> 01:05:53,680 Assim, pp é um apontador para um apontador. 763 01:05:53,680 --> 01:06:02,420 Você está mallocing pp, para apontar para uma matriz de 5 estrelas int. 764 01:06:02,420 --> 01:06:10,950 Assim, em memória que você tem sobre a pilha pp 765 01:06:10,950 --> 01:06:20,150 Vai apontar para uma matriz de 5 blocos que são todos próprios ponteiros. 766 01:06:20,150 --> 01:06:28,210 E então quando eu malloc aqui, malloc eu que cada um desses indicadores individuais 767 01:06:28,210 --> 01:06:32,080 deve apontar para um bloco separado de 4 bytes na pilha. 768 01:06:32,080 --> 01:06:35,870 Portanto, este aponta para 4 bytes. 769 01:06:37,940 --> 01:06:40,660 E isso aponta para uma diferente 4 bytes. 770 01:06:40,660 --> 01:06:43,200 >> E todos eles apontam para suas próprias 4 bytes. 771 01:06:43,200 --> 01:06:49,080 Isto dá-me uma maneira de fazer as coisas multidimensionais. 772 01:06:49,080 --> 01:06:58,030 Eu poderia dizer pp [3] [4], mas agora isso não é a mesma coisa como matrizes multidimensionais 773 01:06:58,030 --> 01:07:05,390 porque as matrizes multidimensionais é traduzido [3] [4] em um único deslocamento para a matriz x. 774 01:07:05,390 --> 01:07:14,790 Este p dereferences, acessa o terceiro índice, em seguida, que dereferences 775 01:07:14,790 --> 01:07:20,790 e acessos - 4 seria inválida - o segundo índice. 776 01:07:24,770 --> 01:07:31,430 Considerando que, quando tivemos a int x [3] [4] antes como uma matriz multidimensional 777 01:07:31,430 --> 01:07:35,740 e quando você dá um duplo suporte é realmente apenas dereference uma única 778 01:07:35,740 --> 01:07:40,490 você está seguindo um único ponteiro e, em seguida, um deslocamento, 779 01:07:40,490 --> 01:07:42,850 isso é realmente referências 2D. 780 01:07:42,850 --> 01:07:45,840 Você segue dois ponteiros separados. 781 01:07:45,840 --> 01:07:50,420 Portanto, esta também tecnicamente permite que você tenha matrizes multidimensionais 782 01:07:50,420 --> 01:07:53,550 onde cada arranjo indivíduo é tamanhos diferentes. 783 01:07:53,550 --> 01:07:58,000 Então eu acho irregulares matrizes multidimensionais é o que é chamado 784 01:07:58,000 --> 01:08:01,870 já que realmente a primeira coisa que poderia apontar para algo que tem 10 elementos, 785 01:08:01,870 --> 01:08:05,540 a segunda coisa que poderia apontar para algo que tem 100 elementos. 786 01:08:05,540 --> 01:08:10,790 [Aluno] Existe algum limite para o número de ponteiros que você pode ter 787 01:08:10,790 --> 01:08:14,290 apontando para outros ponteiros? Não. >> 788 01:08:14,290 --> 01:08:17,010 Você pode ter int ***** p. 789 01:08:18,050 --> 01:08:23,760 Voltar para a aritmética de ponteiro - >> [aluno] Oh. Sim >>. 790 01:08:23,760 --> 01:08:35,649 [Aluno] Se eu tiver int p *** e então eu faço um dereferencing e eu digo p * é igual a este valor, 791 01:08:35,649 --> 01:08:39,560 é que só vai fazer um nível de dereferencing? Sim >>. 792 01:08:39,560 --> 01:08:43,340 Então, se eu quiser acessar a coisa que o último ponteiro está apontando para - 793 01:08:43,340 --> 01:08:46,210 Então você faz p ***. Ok >>. 794 01:08:46,210 --> 01:08:54,080 Portanto, este é p aponta para um bloco, aponta para um outro bloco, aponta para um outro bloco. 795 01:08:54,080 --> 01:09:02,010 Então, se você faz * p = outra coisa, então você está mudando esta 796 01:09:02,010 --> 01:09:13,640 agora a apontar para um bloco diferente. Ok >>. 797 01:09:13,640 --> 01:09:17,649 >> [Bowden] E se estes foram malloced, então você já vazou memória 798 01:09:17,649 --> 01:09:20,430 a menos que você acontecer ter referências diferentes destas 799 01:09:20,430 --> 01:09:25,270 desde que você não pode voltar para aquelas que você só jogou fora. 800 01:09:25,270 --> 01:09:29,550 Aritmética de ponteiro. 801 01:09:29,550 --> 01:09:36,310 int x [4]; vai alocar uma matriz de 4 inteiros 802 01:09:36,310 --> 01:09:40,670 onde x vai para apontar para o início da matriz. 803 01:09:40,670 --> 01:09:50,420 Portanto, quando digo algo como x [1], eu quero que ela signifique ir para o segundo inteiro na matriz, 804 01:09:50,420 --> 01:09:53,319 o que seria um presente. 805 01:09:53,319 --> 01:10:04,190 Mas, realmente, que é 4 bytes na matriz desde que este número inteiro ocupa 4 bytes. 806 01:10:04,190 --> 01:10:08,470 Então, um deslocamento de 1 realmente significa um deslocamento de uma 807 01:10:08,470 --> 01:10:12,030 vezes o tamanho de qualquer que seja o tipo de matriz é. 808 01:10:12,030 --> 01:10:17,170 Este é um array de inteiros, para que ele saiba fazer uma vezes o tamanho de int quando quer compensar. 809 01:10:17,170 --> 01:10:25,260 A sintaxe outro. Lembre-se que isso é equivalente a * (x + 1); 810 01:10:25,260 --> 01:10:35,250 Quando eu digo ponteiro + 1, o que que retorna é o endereço que o ponteiro está armazenando 811 01:10:35,250 --> 01:10:40,360 mais 1 vezes o tamanho do tipo de ponteiro. 812 01:10:40,360 --> 01:10:59,510 Então, se x = ox100, então x + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 E você pode abusar desse e dizer algo como char * c = (char *) x; 814 01:11:19,750 --> 01:11:23,050 e agora c vai ser o mesmo endereço x. 815 01:11:23,050 --> 01:11:26,040 c vai ser igual a ox100, 816 01:11:26,040 --> 01:11:31,490 mas c + 1 vai ser igual a ox101 817 01:11:31,490 --> 01:11:38,030 desde a aritmética de ponteiro depende do tipo do ponteiro que você está adicionando. 818 01:11:38,030 --> 01:11:45,390 Então c + 1, ele olha para c, é um ponteiro char, por isso vai adicionar uma vezes o tamanho do char, 819 01:11:45,390 --> 01:11:48,110 que é sempre vai ser um, para que você obtenha 101, 820 01:11:48,110 --> 01:11:54,890 enquanto que se o fizer x, o qual é também ainda 100, x + 1 vai ser 104. 821 01:11:56,660 --> 01:12:06,340 [Estudante] Você pode usar C + + para avançar o ponteiro por um? 822 01:12:06,340 --> 01:12:09,810 Sim, você pode. 823 01:12:09,810 --> 01:12:16,180 Você não pode fazer isso com x porque x é apenas um símbolo, é uma constante, você não pode mudar x. 824 01:12:16,180 --> 01:12:22,610 >> Mas c acontece de ser apenas um ponteiro, então c + + é perfeitamente válido e será incrementado em 1. 825 01:12:22,610 --> 01:12:32,440 Se c fosse apenas um int *, então c + + seria 104. 826 01:12:32,440 --> 01:12:41,250 + + Aritmética de ponteiro faz exatamente como c + 1 teria feito aritmética de ponteiro. 827 01:12:43,000 --> 01:12:48,870 Este é, na verdade, como um monte de coisas como merge sort - 828 01:12:49,670 --> 01:12:55,710 Em vez de criar cópias de coisas, você pode passar em vez - 829 01:12:55,710 --> 01:13:02,400 Como se eu queria passar esta metade da matriz - vamos apagar um pouco isso. 830 01:13:04,770 --> 01:13:10,520 Vamos dizer que eu queria passar deste lado da matriz em uma função. 831 01:13:10,520 --> 01:13:12,700 O que eu iria passar para essa função? 832 01:13:12,700 --> 01:13:17,050 Se eu passar x, eu estou passando este endereço. 833 01:13:17,050 --> 01:13:23,780 Mas eu quero passar esse endereço particular. Então o que devo passar? 834 01:13:23,780 --> 01:13:26,590 [Estudante] Ponteiro + 2? 835 01:13:26,590 --> 01:13:29,350 [Bowden] Então x + 2. Sim. 836 01:13:29,350 --> 01:13:31,620 Isso vai ser este endereço. 837 01:13:31,620 --> 01:13:42,810 Você também vai muito freqüentemente vê-lo como x [2] e, em seguida, o endereço do. 838 01:13:42,810 --> 01:13:47,850 Então, você precisa ter o endereço dela, porque o suporte é um dereference implícita. 839 01:13:47,850 --> 01:13:53,250 x [2] refere-se ao valor que está na caixa, e então você quer o endereço dessa caixa, 840 01:13:53,250 --> 01:13:56,850 então você diz & x [2]. 841 01:13:56,850 --> 01:14:02,880 Então é assim que algo em merge sort onde você quer passar metade da lista para algo 842 01:14:02,880 --> 01:14:08,790 você realmente só passam & x [2], e agora até a chamada recursiva está em causa, 843 01:14:08,790 --> 01:14:12,510 minha nova matriz começa aí. 844 01:14:12,510 --> 01:14:15,130 Última perguntas minutos. 845 01:14:15,130 --> 01:14:20,050 [Aluno] Se não colocar um comercial ou um - o que é que chama? >> Star? 846 01:14:20,050 --> 01:14:23,200 [Aluno] Star. >> Tecnicamente, operador dereference, mas - >> [aluno] Referência no. 847 01:14:23,200 --> 01:14:29,310 >> Se não colocar uma estrela ou um comercial, o que acontece se eu apenas dizer y = x e x é um ponteiro? 848 01:14:29,310 --> 01:14:34,620 Qual o tipo de y? >> [Aluno] Eu só vou dizer que é ponteiro 2. 849 01:14:34,620 --> 01:14:38,270 Então, se você acabou de dizer y = x, agora x e y ponto para a mesma coisa. >> [Estudante] Ponto para a mesma coisa. 850 01:14:38,270 --> 01:14:45,180 E, se x é um ponteiro int? Seria >> reclamar, porque você não pode atribuir ponteiros. 851 01:14:45,180 --> 01:14:46,540 [Aluno] Okay. 852 01:14:46,540 --> 01:14:51,860 Lembre-se que os ponteiros, apesar de atraí-los como flechas, 853 01:14:51,860 --> 01:15:02,010 realmente loja todos eles - int * x - realmente todo x está armazenando é algo como ox100, 854 01:15:02,010 --> 01:15:06,490 que acontecer para representar como apontando para o bloco armazenado a 100. 855 01:15:06,490 --> 01:15:19,660 Portanto, quando digo int * y = x, eu só estou copiando ox100 em y, 856 01:15:19,660 --> 01:15:24,630 que está indo só para representar como y, apontando também para ox100. 857 01:15:24,630 --> 01:15:39,810 E se eu disser int i = (int) x; então eu vai armazenar qualquer que seja o valor de ox100 é 858 01:15:39,810 --> 01:15:45,100 dentro dele, mas agora ele vai ser interpretado como um inteiro, em vez de um ponteiro. 859 01:15:45,100 --> 01:15:49,310 Mas você precisa do elenco ou então ele vai reclamar. 860 01:15:49,310 --> 01:15:53,300 [Estudante] Então você quer dizer para lançar - 861 01:15:53,300 --> 01:16:00,290 Será que vai estar lançando int de x ou de y int elenco? 862 01:16:00,290 --> 01:16:03,700 [Bowden] O que? 863 01:16:03,700 --> 01:16:07,690 [Aluno] Okay. Após estes parênteses está lá vai ser um x ou ay lá? 864 01:16:07,690 --> 01:16:11,500 >> [Bowden] De qualquer. x e y são equivalentes. >> [Aluno] Okay. 865 01:16:11,500 --> 01:16:14,390 Porque eles são os dois ponteiros. Sim >>. 866 01:16:14,390 --> 01:16:21,050 [Estudante] Então seria armazenar os 100 hexadecimal na forma inteiro? >> [Bowden] Yeah. 867 01:16:21,050 --> 01:16:23,620 Mas não o valor de tudo o que ele aponta. 868 01:16:23,620 --> 01:16:29,940 [Bowden] Yeah. >> [Aluno] Então, apenas o endereço em forma de número inteiro. Okay. 869 01:16:29,940 --> 01:16:34,720 [Bowden] Se você quisesse, por alguma razão bizarra, 870 01:16:34,720 --> 01:16:38,900 você poderia exclusivamente lidar com ponteiros e nunca lidar com números inteiros 871 01:16:38,900 --> 01:16:49,240 e apenas ser como int * x = 0. 872 01:16:49,240 --> 01:16:53,000 Então, você vai ficar muito confuso, uma vez aritmética de ponteiro começa a acontecer. 873 01:16:53,000 --> 01:16:56,570 Assim, os números que eles armazenam são sem sentido. 874 01:16:56,570 --> 01:16:58,940 É exatamente como você acaba interpretá-las. 875 01:16:58,940 --> 01:17:02,920 Então, eu estou livre para copiar ox100 de um * int para um int, 876 01:17:02,920 --> 01:17:07,790 e eu sou livre para atribuir - você é, provavelmente, vai ser repreendidos por não lançar - 877 01:17:07,790 --> 01:17:18,160 Eu sou livre para atribuir algo como (int *) ox1234 neste int * arbitrária. 878 01:17:18,160 --> 01:17:25,480 Então ox123 é tão um endereço válido de memória como é e y. 879 01:17:25,480 --> 01:17:32,060 & Y acontece para retornar algo que é muito bonito ox123. 880 01:17:32,060 --> 01:17:35,430 [Aluno] Teria que ser uma forma muito legal para ir de hexadecimal para a forma decimal, 881 01:17:35,430 --> 01:17:39,230 Como se você tiver um ponteiro e lançá-lo como um int? 882 01:17:39,230 --> 01:17:44,860 [Bowden] Você pode realmente apenas imprimir usando como printf. 883 01:17:44,860 --> 01:17:50,300 Vamos dizer que eu tenho int y = 100. 884 01:17:50,300 --> 01:18:02,700 Então printf% (d \ n - como você já deve saber - que imprimir como um inteiro x,%. 885 01:18:02,700 --> 01:18:05,190 Nós apenas imprimi-lo como hexadecimal. 886 01:18:05,190 --> 01:18:10,760 Assim, um apontador não é armazenado como hexadecimal, 887 01:18:10,760 --> 01:18:12,960 e um número inteiro não é armazenado como decimal. 888 01:18:12,960 --> 01:18:14,700 Tudo é armazenado como binário. 889 01:18:14,700 --> 01:18:17,950 É que nós tendem a mostrar ponteiros como hexadecimal 890 01:18:17,950 --> 01:18:23,260 porque pensamos de coisas nesses blocos de 4 bytes, 891 01:18:23,260 --> 01:18:25,390 e endereços de memória tendem a ser familiar. 892 01:18:25,390 --> 01:18:28,890 Nós somos como, se ele começa com bf, então ele passa a ser na pilha. 893 01:18:28,890 --> 01:18:35,560 Então é só nossa interpretação de ponteiros como hexadecimal. 894 01:18:35,560 --> 01:18:39,200 Okay. Qualquer dúvida últimos? 895 01:18:39,200 --> 01:18:41,700 >> Eu estarei aqui para um pouco depois, se você tem qualquer outra coisa. 896 01:18:41,700 --> 01:18:46,070 E esse é o fim de tudo. 897 01:18:46,070 --> 01:18:48,360 >> [Aluno] Yay! [Aplausos] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]