[Powered by Google Translate] [Semana 4, continuación]
[David J. Malan - Harvard University]
[Esta é CS50. - CS50.TV]
>> Este é CS50, e este é o fin de semana 4.
Entón, unha noticia boa e unha mala noticia.
Non charla o luns, non hai problema definido a próxima semana. [Alumnos aplaudindo]
Non vai gusta de onde iso vai dar.
Pero nós temos iso en vez vindeiro mércores,
e hai tamén o currículo por charla venres unha vindeiro venres, para que poidamos permanecer na pista.
Pero todo vai ser filmado, como de costume, para non se preocupar.
>> E con relación a 0 Quiz o que imos facer para o final da semana
é publicar en cs50.net do curso sitio web unha explicación
que tipo de expectativas que debe ter cando se trata do primeiro cuestionario.
En xeral, será de múltiple opción, verdadeiro ou falso, resposta curta curtas problemas de codificación.
Non vai ser esperado para aplicar o equivalente
dun problema que vería nun pset, para que teña un ordenador
e un depurador e similares, pero non haberá pequenos problemas de codificación.
>> E, de feito, o mellor guía para ter unha noción do que son como CS50 quizzes
é ir a cs50.net, ir ao enlace quizzes,
e podes ver os últimos anos por valor de cuestionarios.
Basta entender que o currículo non foi sempre o mesmo ao longo dos anos.
Ás veces, engadimos nós, ás veces, restar,
entón se ves algún tema nun dos vellos quizzes
que non ten idea do que está falando, ela quere que sexa abordado
ou que non cobre-lo.
Pero, na forma de comentarios, este domingo, luns e martes
así como un curso de ancho sesión de revisión, na noite do domingo -
horario e lugar a ser anunciado na páxina principal do curso -
que todos teñan a oportunidade de revisar os bolseiros do curso de ensino
material para este ano, tanto na sección e como unha clase chea,
e os que serán filmados, como de costume tamén.
>> Todo ben. Entón, sen máis delongas, un comentario sobre aprobación / reprovação e add / drop.
Podes ver as miñas notas na noite pasada, e iso é realmente só algúns garantía adicional
que, se está entre os particularmente menos cómodo ou nalgún lugar entre
e se está sentindo un pouco por riba da súa cabeza,
entender que é realmente moi normal, e non hai unha estrutura de apoio ampla no lugar,
un dos cales o horario de expediente tiñan a intención de mellorar aínda máis a miña noite para rematar e-mail,
e entender tamén que unha opción como aprobación / reprovação dunha clase como esta
realmente se entende como un mecanismo para tomar a bordo fóra dun curso coma este,
para que de novo se está gastando os 10, 15, 20 horas
só tentando obter algunha pset para traballar e vostede sabe que é 90-95% do camiño
pero non pode atopar algún erro maldito, nun aprobación / reprovação modelo que é unha especie de ben.
>> A idea é que, con este mecanismo, pode ir foco nas súas outras serie de exercicios
ou durmir ou que é o que quere centrar.
Entón entender que ten ata esta martes que vén - técnicamente o luns 5,
pero é unha festa, para esta martes que vén - para cambiar de aprobación / reprovação para graduados ou viceversa.
E se está realmente ao bordo do precipicio e está a pensar en deixar caer por completo,
por favor me incorporarse despois de charla ou mandar-me unha nota.
Adoraríamos polo menos conversa antes de despedirse.
Todo ben. Entón comezan a retirar as rodinhas da última vez.
En particular, nós nos concentrados en secuencia.
Cadea é algo que é declarado na biblioteca CS50,
especialmente no arquivo chamado cs50.h que nós imos comezar a ollar para esta semana ea próxima.
Pero cadea é realmente só unha simplificación de algo
que é un pouco máis arcanely descrito como char *.
Char estamos familiarizados. É só un único personaxe.
Pero * como de luns denotado o que? >> [Alumno] Un punteiro.
Un punteiro. E o que é un punteiro? >> [Alumno] Un enderezo.
>> É como un enderezo, un lugar na memoria.
¿Que é un enderezo ou lugar ou de memoria?
Unha vez máis, todos temos portátiles con un concerto ou 2 gigabytes de memoria RAM probablemente estes días,
e iso significa que ten un billón ou 2 millóns de bytes por valor de memoria.
E iso realmente non importa o que fisicamente se parece,
pero asumir a fe que pode numerar todos os bytes individuais que ten o seu propio portátil -
este é o byte 0, este é un byte, este é byte 2 millóns -
e iso é o que un ordenador fai.
Cando reservar espazo para un único personaxe, por exemplo,
que, obviamente, ten que vivir en algún lugar na memoria do seu ordenador,
e quizais sexa, o número de bytes 12345,
e que está en algún lugar aquí en memoria do seu ordenador.
E o enderezo logo de que o carácter é 12345.
>> Agora, a semana 0 por agora, ata agora, non temos realmente lle importaba
onde na memoria as cousas están gardados porque xeralmente usan símbolos,
variables, e matrices para realmente obter os nosos datos.
Pero a partir de luns e aínda máis hoxe, agora vai ter
todos os recursos máis expresivos con programas de escritura
para realmente manipular a memoria dun ordenador, con todo, ve o axuste,
tanto para fins bos e malos,
erros de ser un resultado moi común neste punto en aprender esas cousas.
Pero o que iso realmente significa ser un char *?
Imos en fronte de volta para - e nós imos voltar a Binky como prometera hoxe.
Imos a un exemplo simples aquí.
Deixe-me salve este ficheiro como compare.c, e deixe-me conseguir algún código do modelo aquí
para incluír stdio.h, deixe-me dar-me tamén inclúen cs50.h. Vou aumentar o zoom ata alí.
Deixe-me comezar a escribir int main, main (void), e agora quero facer algo como isto:
printf ("Deixa-me unha cadea:") e logo vou usar string s está GetString
para obter unha cadea de usuario, entón eu vou pedir para o usuario a outra.
("Deixa-me outra cadea:") e eu vou pedir a eles a través GetString para conseguir isto.
Vou chamalo de t t porque vén despois de s e s é un bo nome para unha cadea se é moi xenérica.
Entón GetString, e agora eu só quero facer unha proba de sanidade e eu vou dicir
if (s == t), entón eu vou só dicir que o usuario printf ("Inseriu o mesmo \ n");
máis eu vou imprimir algo ("Inseriu algo diferente! \ n")
ou calquera que sexa a sentenza será. Entón, algo así.
A continuación, como de costume, eu vou volver 0 que só significa que nada de malo aconteceu,
e eu estou indo a ir adiante e compilar e executar este programa.
>> Pero o luns nos rodamos este programa,
e, de feito, foron informados de que non é OLA OLA adeus e non é un adeus.
O comportamento que vimos foi un pouco máis como este.
Deixe-me ir para o meu directorio de orixe, zoom aquí, e imos facer comparar.
Compilado ben. Déixame executar comparar. Déame unha cadea: Ola.
Déame outra secuencia: Ola.
Escribiu algo diferente!
Ben, deixe-me tentar algo máis simple como 50, 50. Escribiu algo diferente!
ola, ola. Entón, claramente, algo está a suceder aquí.
Pero cal era a explicación para por que?
Ao parecer, a liña 12 é completamente disfuncional.
Cal é o problema fundamental aquí? Si >> [Alumno] Está comparando os enderezos.
Si, exactamente. É realmente comparando os enderezos
en que OLA OLA e son almacenados.
Non está comparando as letras OLA novo e de novo,
porque o que realmente aconteceu, todo ese tempo que estamos usando GetString -
Este cadro é unha vez máis a memoria do noso ordenador,
e digamos que eu chamo GetString despois de declarar unha variable s.
Por que a miña memoria parece?
Imos dicir que arbitrariamente s parece con isto. É un cadrado.
E practicamente calquera tempo eu deseño un anaco de memoria na pantalla
si é 32 bits eu teño deseñado cadrados como este, porque realmente o aparello,
un punteiro, un enderezo, é de 32 bits. É o mesmo que un int.
Isto pode variar de acordo co sistema informático.
Aqueles de vós que son vagamente familiarizado co feito de que o seu Mac ou PC de 64 bits,
que, en realidade, indica que o ordenador está a usar punteiros de 64 bits,
64-bits de enderezos, e entre os dous lados positivos de que é os seus ordenadores
RAM pode ter moito máis do que antigamente.
Longa historia curta, de volta ao día en que os ordenadores usados ​​só 32 bits
para representar os enderezos, o maior número de bytes que podería representar
nese caso, foi o que se ten 32 bits?
Entón 4 millóns, dereito, porque 2 a 32 e de 4 millóns.
Este número foi recurrente no curso.
>> Entón, se só ten 32 bits, o número máis alto que pode contar para a preto de 4 millóns de dólares.
Pero iso era unha limitación fundamental dos ordenadores, ata uns anos
porque se só pode contar ademais de 4 millóns,
non importa se mercar 8 gigabytes de memoria RAM ou ata 5 gigabytes de memoria RAM;
non pode contar que a alta, polo que era inútil.
Vostede podería acceder só os primeiros 3 ou 4 gigabytes de memoria do seu ordenador.
Iso é menos de un problema, e pode mercar MacBook Pros e Dells
con 8 gigabytes de memoria RAM ou mesmo máis estes días.
Pero se eu simplemente reservar neste programa un punteiro, un punteiro chamado s,
pode parecer que está na pantalla, pois realmente necesitamos descascada esa capa.
Eu sigo dicindo cadea, pero a partir de luns, string é realmente * char,
o enderezo de algún personaxe.
Polo tanto, imos ter que roda formación fóra aínda que nós imos seguir usando GetString por agora.
Entón eu s declarada, e este é un anaco de memoria, 32 bits.
O que ten aquí en memoria por defecto? >> [Resposta do alumno inaudível]
¿Que é iso? >> [Alumno] Lixo. Lixo. >> Exactamente.
Se o desenvolvedor non poñer un valor nunha variable, que sabe o que é?
Ás veces tes sorte e é 0, que é unha especie de bo valor por defecto, limpo,
pero como vimos luns, ás veces, é un disparate completo,
un número moi grande positivo ou negativo que veu de onde?
Si >> [Estudante] A función antes. Si >>.
>> Moitas veces a función que foi chamado antes, porque lembre,
como chama funcións na memoria, eles ocupan máis espazo e máis de abaixo cara arriba,
e, logo que o retorno da función, que a memoria está reutilizado
polo próximo cara que se chama, quen está a usar o mesmo porción de memoria.
E se ten lixo deixado alí, os valores anteriores,
podemos confundir s como tendo un valor cando realmente non puxémonos nada alí.
Polo tanto, a nosa memoria RAM, neste punto parece con isto.
Agora, no lado dereito da liña 7 estamos chamando GetString,
que estamos facendo agora por semanas, pero o que é realmente GetString facendo?
GetString escrito polo equipo do CS50 é un pouco intelixente
en que, así que o usuario comeza a teclear as teclas e hits Intro,
Figuras GetString fóra cantas teclas fixeron o éxito do usuario,
cantos caracteres eu teño reservar memoria RAM para.
E onde que a RAM vén, quen sabe?
Está en algún lugar do seu ordenador 2 gigabytes de memoria e outros enfeites.
Pero imos supor que o ordenador atopou espazo para a palabra OLA aquí.
A palabra que eu escriba foi H-E-L-L-O.
E se tomar isto como unha secuencia de caracteres, pode chamar así.
Pero eu teño que facer unha cousa extra. O que pertenza ao final de calquera cadea en C?
O personaxe nulo, o que escribir como \ 0.
É técnicamente o número 0, pero a barra invertida fai toda máis clara a
que este é literalmente o número 0, o enteiro 0;
non é, por exemplo 0, entre comiñas que pode escribir no teclado.
Polo tanto, esta é OLA.
>> E o que podemos dicir luns que unha función como GetString
é, en realidade, volvendo todas estas semanas?
Non é devolver unha cadea de per se, porque iso realmente non ten sentido
porque as cordas non existen. Son unha especie de fabricación na biblioteca CS50.
O que é realmente unha secuencia, máis tecnicamente? >> [Alumno] É o primeiro carácter.
Exactamente. É simplemente o enderezo do primeiro carácter que o usuario introduciu dentro
Entón, a miña palabra OLA remata-se en 123 o número de bytes e logo en número de byte 124,
125, 126, e así por diante, se número só os meus máis de 0 encima,
o que realmente está retornando GetString é literalmente o número 123.
Entón, o que é posto en s é o número 123, e non a letra H, non a palabra OLA,
simplemente o enderezo en que eu poida atopar a primeira letra do OLA.
Pero iso non parece ser suficiente. Eu lle pedín unha cadea, non un personaxe.
Así coma nós ou o ordenador saber que tipo de ello veñen xunto co H?
Cal é o tipo de acordo que temos? Si
[Alumno] Continúa dicindo a si mesma para atopar algúns personaxes. >> Exactamente.
>> Hai esa convención humano-ordenador en que cando está lidando con cordas,
tamén coñecido agora como estrelas char, simplemente ten que descubrir
onde ao final de cada corda na vida é realmente só unha iteração sobre iso con un loop,
un loop while, calquera que sexa, de xeito que cando atopa o final da cadea
agora pode inferir que, oh, toda a palabra foi OLA.
Aqueles de vós con experiencia previa en programación pode saber en Java
pode só chamar. lonxitude e noutras linguas pode chamar lonxitude ou similar.
Isto porque unha morea de linguas, especialmente cousas chamadas linguaxes orientadas a obxecto,
a lonxitude de algo é unha especie de encapsulado dentro dun anaco de datos en si,
moi coma nós IDs encapsulados e nomes e casas dentro dun estudante luns.
Pero C é o nivel máis baixo. Non hai obxectos ou clases, se vostede xa escoitou estes termos antes.
Todo o que tes é realmente enderezos de memoria.
Polo tanto, esta é unha especie de maneira antiga de representar estruturas interesantes datos.
Ten un valor inicial como o enderezo do primeiro carácter
e despois é só convención algúns arbitraria que todos están de acordo en seguir.
Entón, como é aplicada lonxitude da corda, que propoñemos?
Strlen, strlen, que algúns de vós xa usado algunhas veces. É moi sinxelo, non?
É coma se dúas liñas de código.
É practicamente un lazo para dalgunha sorte, quizais cunha variable adicional local.
Pero strlen só ten que tomar un punteiro e, a continuación, comezar a ollar para \ 0.
>> E así que atopar, pode voltar o número total de pasos que é tomado en que secuencia.
Así, podemos deducir o que pasa ao carón.
Supoña entón eu declaro t como eu fixen na liña 10.
Trátase de un valor de lixo. Quen sabe o inicio?
Pero no lado dereito da liña de 10 que eu estou chamando GetString novo.
Quen sabe onde iso acaba?
Imos arbitrariamente dicir que o sistema operativo atopou espazo para el camiño ata aquí.
Acontece que eu casualmente tipo H-E-L-L-O de novo,
e así podemos chamar o mesmo tipo de imaxe.
Pero o feito de que eu teño esta foto redeseñado é deliberada
porque esa é unha. OLA diferente do que esta
Polo tanto, aquí este pode ser local 456, este é 457, e así por diante.
Entón, o que é colocado onde o punto de interrogación era unha vez?
Neste caso 456.
Estamos collendo estes números arbitrariamente porque realmente despois de hoxe
nós non imos importar tanto co que o enderezo de calquera cousa é.
Todo o que importa é que podemos atopar o enderezo de calquera peza de datos como OLA.
>> Entón, realmente o que a maioría da xente en ciencia da computación cando se fala de enderezos de memoria
e falando sobre punteiros en concreto,
en vez de se preocupar descubrir 123 - quen se importa onde este material realmente é,
só sabemos que está en algún enderezo numérico -
que simplifican o mundo e só dicir que s está vinculado a que o personaxe
e t está a apuntar cara ese personaxe.
E o feito de que é unha frecha é moi intencionada
porque agora literalmente s está a apuntar cara H e T está apuntando para o outro H
porque ao final do día, que non importa cal é a dirección é,
pero non importa de que temos a capacidade de expresar ese enderezo con algún anaco de código.
Nós realmente non temos manipulado estes enderezos só aínda
entón imos ver onde podemos interpoñer e clasificar de facer as cousas con punteiros,
pero por agora na liña 12, literalmente, os valores que estamos comparando
de acordo con esa historia na liña 12?
Estamos dicindo é 123 igual igual a 456? E iso non é sempre o caso.
E mesmo conceptualmente, ese punteiro definitivamente non é o mesmo que este
porque chamou GetString dúas veces, e GetString non intenta ser super intelixente,
non tente entender, oh, escribiu OLA cinco minutos;
deixe-me dar-lle o mesmo punteiro como lles dei antes,
el só aloca un novo bloque de memoria cada vez que chamalo.
>> Entón, como imos resolver este problema?
Se nivel máis alto Eu quero comparar as cordas Ola e OLA -
Eu non me importa os punteiros - como fago para responder a pregunta,
se o usuario escribe o mesmo? O que fai falta aquí? Si
[Estudante] Usar a función. >> Eu podo usar unha función fóra da caixa.
Podo usar unha función chamada strcmp, s-t-r-c-m-p,
só a versión abreviada de dicir corda comparar.
E se entrar, por exemplo, comparar dous, que está entre folletos de hoxe,
Fago exactamente isto.
Eu mantiven todo o mesmo a partir dunha liña para abaixo, para 26 ou máis,
e agora entender esta parte cambiou un pouco.
Imos ignorar a liña 28 por un momento e concentrarse só en un regalo.
O que nós dicimos luns que str comparación fai?
El trata sobre o proceso de tomar dous punteiros, S e T, neste caso,
especie de practicamente poñendo o dedo sobre estas dúas cartas,
eo que debe facer é algo así como un loop while ou un loop for,
e el di que son estes os mesmos? Se é así, move os dedos ou punteiros para adiante.
Son estes os mesmos, estes mesmos o, estes, o mesmo
estes mesmos o, eses mesmos a? E Ooh, eu estou no final da cadea, tanto s e t.
Non se atoparon calquera contradicións. Si, esas secuencias son as mesmas.
E o que str retorno comparar dúas cordas son os mesmos, aparentemente? Cero.
Entón, 0 é bo neste caso, porque se volve -1 ou +1,
Isto significa que só acontece de vir antes de t en orde alfabética ou despois de t.
E por que iso sería útil ter unha función que lle di que a corda chega antes
ou despois dun dicionario?
[Alumno] Buscando. >> Investigación e clasificación.
>> Así, pode facer cousas como busca binaria ou especie de burbulla ou merge sort
onde ten que comparar as cousas.
Ata agora, nós medio que cortar algúns recunchos e só falou sobre a clasificación
no contexto de números, porque é agradable e doado de falar,
pero certamente pode comparar cadeas, mazá e plátano,
porque se mazá é coñecido por vir antes da banana, do mesmo xeito,
pode mover cordas en torno á memoria como Rob fixo merge sort no vídeo
e nós fixemos aquí no escenario cunha especie de selección, tipo de inserción, e especie de burbulla.
Entón, onde máis podemos facer iso? Imos tentar iso.
Imos esquecer que tipo de lección para un momento e ténteo agora e copiar 1.c para facer o seguinte.
Na liña 21 eu estou dicindo algo de impresión,
entón eu estou recibindo unha cadea de usuario,
entón eu estou comprobando isto.
Nós realmente non temos chegado a este hábito aínda, pero imos facelo agora.
Imos realmente descascada esa capa. Isto é realmente char *. Este cara é moi char *.
Entón, o que significa estar comprobando se s == null?
Acontece que cando chamar a unha función como GetString
ou, máis xeralmente basta preguntar a un ordenador para lle dar un pouco de memoria,
algo podería dar mal.
Vostede podería estar tolo e pedir ao ordenador para un terabytes de memoria
pedindo billóns de bytes de memoria que simplemente non existen no ordenador,
pero funcións GetString e outros precisan de algunha forma de berrar con vostede
se pediu moito.
E o xeito GetString fai iso é, se pediu máis memoria
que está dispoñible no seu ordenador, mesmo se iso é super, super baixa probabilidade
porque ningún de nós está indo para escribir un billón de caracteres e preme a tecla Intro,
pero baixa probabilidade que poida ser, eu aínda quero para comprobar iso só no caso,
eo valor especial que retorna GetString, resposta, e outras funcións
algo deu mal é NULL en todas as tapas.
>> E o que é NULL? NULL só acontece a representar un punteiro. É 0 enderezo de memoria.
O mundo decidiu que arbitrariamente, esta é a memoria do meu ordenador - vostede sabe o que? -
imos roubar só 1 byte de memoria cada ordenador, e esta é a posición 0.
Nós imos darlle un apelido de NULL, e imos prometer
que nunca imos realmente poñer datos reais alí
porque só arbitrariamente precisa dun valor especial, 0, NULL aka,
para que poidamos berrar cos usuarios, se algo sae mal.
Se non, pode non saber é que 0 significa poñer algo aquí
ou significa algo deu mal?
Temos que aceptar que non significa nada NULL foi devolto,
ningún enderezo real foi devolto.
Agora, aquí estou só adoptar meu convenio humana de volten unha da principal
se algo sae mal.
Isto porque principal convención de retorno e voltar 0 se ben,
Un ou outro valor mal.
Pero GetString e calquera función que se ocupa en memoria retorna NULL se algo vai mal.
>> Okay. Entón, por desgraza, liña 27, super sinxelo que sexa, completamente fallo ao copiar a cadea.
Por que? Podemos ver isto como segue.
Eu estou afirmando na liña 27 para facer unha copia de s e chamándoo de t.
Entón eu non estou pedindo ao usuario para 2 cordas esta vez, estou só dicindo o valor en s
deben ser colocados en t tamén.
Entón agora só para demostrar como este é roto, na liña 29 en diante o que eu estou facendo?
Primeiro estou comprobando se a lonxitude da t é maior que 0.
Hai algunha corda alí. O usuario escribiu algo dentro
Cal é a liña 32, facendo aparentemente?
[Resposta do alumno inaudível] Dereito. >> Podes tipo de inferir-lo de que eu dixen que está facendo.
Pero, tecnicamente, o que se está facendo? t [0] representa o que?
[Alumno] O personaxe 0. >> [Malan] O personaxe 0.
Ou, máis semellante á humana, o primeiro carácter en t, o que quere que sexa, H quizais neste caso.
E toupper fai o que di. El conta o carácter de t 0 e cambia-la.
Entón iso significa tomar o carácter de t 0, facelo maiúsculas,
e poñelas de volta no mesmo lugar.
Entón, se eu escribir Ola en letras minúsculas, que debe cambiar a h minúsculas para un H. de capital
Pero o problema é que, en liñas 35 e 36 o que eu estou a piques de facer é imprimir para nós s e t.
E cal é o seu palpite?
O que eu estou indo realmente para ver se eu escriba Ola en todas as minúsculas?
O que se ve impreso? >> [Resposta do alumno inaudível] >> ¿Que é iso?
[Alumno] Big H eo resto pequeno. H >> O grande e pequena para o resto, que, s ou t?
[Alumno] Ambos. Tanto >>. Exactamente. Entón, imos ver o que está a suceder aquí.
>> Deixe-me ir adiante e compilar este. Este é copy1, para facer copy1. Todo ben.
Zoom dentro Deixe-me ir adiante e executar copy1, Intro, dicir algo: Ola en minúsculas.
El capitalizar a copia, pero, ao parecer, capitalizados o orixinal, así como,
porque o que agora ocorre nesta historia?
Na liña 27 eu realmente non parecen estar a copiar a cadea,
pero que pode ter a esperanza de que intuitivamente ser o caso,
Se pensar sobre ese cadro, o que realmente eu fixen?
Metade do cadro é o mesmo.
Entón, imos voltar a tempo para que t aínda non existe na historia.
S pode existir na historia, pero imos minúsculas Ola neste momento.
Entón deixe-me corrixir o que realmente ingresaran dentro
Neste caso, temos aquí H-e-l-l-o.
Imos deseña-lo como unha secuencia de caracteres, poñer as miñas liñas separadoras aquí e meu \ 0.
Polo tanto, este é o lugar onde estamos, así como a liña de 1 a 24-ish, máis ou menos, ter executado.
Esta é a imaxe da miña memoria.
Cando chegar á liña 27, que pasa?
Así como antes, eu recibín un punteiro, que eu vou deseñar como esta praza.
É chamado de t. E o que é o seu valor por defecto? Quen sabe? Un valor lixo.
>> Entón eu vou abstracta que fóra como un punto de interrogação.
E logo que o lado dereito da liña 27 executa, o que estou poñendo dentro de t?
A mesma cousa que está en s.
Entón, se por un momento eliminar esa abstracción da frecha e dicimos:
oh, este é o enderezo de memoria de carga 123, cando di que queda t s, punto e coma,
está literalmente poñendo 123 aquí.
Agora, se nós tipo de simplificar o noso mundo novo con fotos,
o que realmente está feito só engadiu outra frecha para o mundo
que está apuntando t para a mesma secuencia exacta.
Así, cando na liña 31 e 32 realmente ir sobre o cambio de t [0]
o que é t [0] parecer sinónimo de agora? s [0]
Entón, iso é todo o que está a suceder.
E aínda que este tipo de sente un nivel un pouco baixo e arcano
e este tipo de sensación, talvez intuitivamente este debería ter só traballado -
Fixen copias de cousas antes e só traballou -
se realmente pensar sobre o que realmente é unha cadea, é un char *.
Ben, o que é iso? É o enderezo de algún personaxe.
Entón, talvez, fai máis sentido que, cando intenta facer algo
Super aparentemente simple como este, todo o que está facendo é copiar o enderezo dunha memoria.
Vostede non está realmente facendo algo coa secuencia en si.
Así, mesmo se non ten idea de como podería solucionar este problema no código,
alto nivel, conceptualmente, o que necesitamos facer para facer ta copia fiel da s, aparentemente?
Si >> [Alumno] Dele un novo local? >> Exactamente.
>> Necesitamos dar t un lugar novo.
Necesitamos algunha maneira crear un mundo no que temos un novo bloque de memoria,
que só por unha cuestión de claridade eu vou deseñar debaixo un agasallo, pero non precisa estar alí.
Pero ten que ser do mesmo tamaño, entón eu vou sacar esas liñas verticais no mesmo lugar.
É bo se todo isto é lixo inicialmente. Quen sabe o que estaba alí?
Pero, mentres un vai ter que ser darme tanta memoria que eu teño
para atender a unha copia do Hola, a continuación, descubrir como copiar o h aquí, o e aquí,
o l, aquí e así por diante.
Pero iso xa debería sentirse un pouco evidente, aínda que algúns dos detalles aínda son abstractos.
Para copiar esa cadea para iso, é só un loop ou un loop while
ou algo que se tornou aínda máis familiar.
Entón, imos tentar iso. Deixe-me ir copy2.c.
En copy2.c temos case o mesmo programa, excepto para a liña 27.
Parece un pouco complexo, pero se decompô-lo peza por peza,
á esquerda é o mesmo.
Char * t crea esa cousa na memoria, aínda que con un punto de interrogação
porque non temos idea do que está alí por defecto.
No lado dereito, estamos agora a introducir unha nova función malloc,
para reservar a memoria, dáme a memoria,
e ao parecer leva cantos argumentos, cantas cousas dentro parénteses?
Eu oín murmurios de 1 e 2, pero é só unha.
Non hai coma, o que significa que hai só unha cousa un dentro dos parénteses.
Aínda que non haxa parénteses outros, deixe-me salientar
o que está dentro dos parénteses ultraperiféricas, e é esta expresión:
(Strlen (s) + 1) * sizeof (char).
Entón, se nós realmente pensar niso, este está dicindo me dar a lonxitude de s.
Por que eu son, porén, engadindo 1 para a lonxitude? >> [Resposta do alumno inaudível]
Exactamente. Necesitamos espazo para este cara na cola, o sexto carácter que non ten sentido Inglés
pero ten significado programático especial.
>> Entón necesitamos un + 1 para que, porque strlen retorna a esperanza humana de lonxitude,
Ola ou 5, non lle dá o carácter nulo adicional.
Entón eu engadir manualmente isto con + 1.
E despois diso, tamaño * de (char), non vimos isto antes.
Este non é, tecnicamente, unha función.
É unha palabra clave especial que só di que o tamaño é de calquera tipo de datos nun ordenador
porque, en realidade, algúns de nós temos ordenadores de 32 bits.
Eu teño un ordenador moi vello na casa, e só usa 32 bits para representar punteiros.
E así, se eu fixen tamaño dun tipo de datos, pode ser de 32 bits.
Pero se eu estou usando o meu novo ordenador fantasía, eu poida volver un valor de 64 bits
para algo así como un enderezo.
Polo tanto, neste caso, só para ser seguro super, non imos a algo ríxido código como -
ben, o que é do tamaño dun char de acordo co que dixemos ata agora?
Nós practicamente dixo verbalmente que é un byte, e iso é moi fermoso realidade a través da tarxeta.
Pero, de novo, os presupostos tenden a ser malo.
Eles levan a software buggy as persoas usan o seu programa de forma que non tivo a intención.
Entón imos abstracto esta distancia é só xenericamente dicir
Eu teño diso moitos anacos de memoria
e cada bloque de memoria debe ser equivalente ao tamaño dun personaxe,
que é de feito igual a 1 neste caso, pero é unha forma máis xenérica de escribilo.
Entón, se a palabra é Ola, cantos bytes se malloc aparentemente reservar para Ola?
[Alumno] Six. >> Six. Exactamente como moitos como temos puntos de interrogación na pantalla.
E despois dar un palpite agora baseada na súa comprensión de GetString
o que malloc probablemente volver? >> [Alumno] Un enderezo.
Un enderezo de que? Do primeiro anaco de memoria.
>> Nós non temos idea do que está aí porque algunha outra función
podería ser mediante a memoria anteriormente.
Pero malloc, como GetString, retorna o enderezo do primeiro byte de memoria
que ten reservado para ti.
Con todo, o que non fai é encher este baleiro cun carácter nulo barra invertida
pois verifícase que pode usar malloc para reservar calquera cousa: ints, cadeas, arrays,
coches alegóricos, estruturas estudantís.
Podes empregar malloc completamente xenericamente.
Non importa ou ten que saber o que está alocando memoria para.
Polo tanto, sería presunçoso para malloc para colocar un \ 0
ao final de cada peza de memoria que está dando a vostede
porque esta \ 0 cousa é só unha convención para cordas.
Ela non se usa para ints, ela non é usada para coches alegóricos, ela non é usada para os alumnos.
E así a pegadinha co malloc é que a carga é enteiramente de ti o programador
lembrar cantos bytes lle asignado e non para nunca usar un lazo
ou un loop while e ir alén do límite do bloque de memoria que ten dado.
Dito doutra forma, tan pronto se reservar memoria
non pode pedir o sistema operativo, oh, a propósito, o tamaño dun bloque de memoria foi iso?
É enteiramente ata lembrar se precisa ese valor.
>> Entón, imos ver como eu continuar a utilizar esta memoria.
Na liña 28 e 29, por que estou facendo isto?
Basta comprobar a sanidade total.
Só no caso de algo sae mal, eu pedir algunha cantidade tola de memoria
ou eu teño tantas cousas en execución no ordenador que simplemente non hai memoria suficiente,
algo así, eu polo menos quero para comprobar nulo.
En realidade, a maioría dos ordenadores vai dar a ilusión de que todos os programas
pode utilizar a totalidade da súa memoria RAM,
pero, aínda así, se o usuario escribe algunha corda tolo longa quizais porque é un cara malo
e eles están realmente intentando frear o seu programa ou hack para el,
quere, polo menos, verificar o valor de retorno de malloc e iguala nulo.
E se isto acontecer, imos deixar agora porque eu non sei o que facer nese caso.
¿Como copiar a cadea? Hai algunhas formas de facelo.
Hai str copiar funcións en C, pero é super sinxelo para nós para facelo do xeito old-Fashioned.
>> Primeiro déixeme descubrir o que a lonxitude de s.
Eu podería ter colocado iso no loop, pero en vez diso, simplemente poñelas aquí para maior claridade.
Entón n agora almacena a lonxitude da cadea orixinal, o que aparentemente é 5.
Entón, no meu lazo para Estou interactuar 0 ata n,
e en cada iteração eu estou poñendo s [i] dentro de t [i].
Entón é iso que eu implicaba cos meus dous dedos apuntando cara as cordas antes.
Como este lazo for así, eu vou estar copiando h en aquí,
e aquí, eu para aquí porque este é s, este é t.
E entón, finalmente, na liña 35, por que estou facendo isto?
Eu teño que seguro que eu estou rematando o t string.
E eu fixen iso desa maneira de ser super explícito.
Pero propoñer, alguén, se puidese, unha forma diferente de facelo.
Eu realmente non precisa de liña 35. Hai outra forma de facelo.
Si >> [Resposta do alumno inaudível] >> Diga máis alto.
[Estudante] Menos do que ou igual a. >> Exactamente.
Poderiamos só dicir menos que ou igual a n, o que en xeral ten sido mal
porque case sempre cando imos a un igual á cousa estamos contando
imos un paso lonxe de máis.
Pero lembre, cantos bytes que reservar?
Alocamos strlen de s, para 5 + 1, para un total de 6.
Polo tanto, neste caso, poderiamos facer algo así
de xeito que estamos copiando non só o Ola pero tamén a 0 \ ao final.
Alternativamente, poderiamos usar unha función chamada str copia, strcpy,
pero iso non sería divertido case tanto como.
Pero iso é todo o que fai debaixo do capó.
Entón, por fin, facemos o mesmo que antes.
Eu t capitalizar e eu afirmo que o orixinal é así ea copia parece así.
Entón, imos tentar iso agora. Deixe-me ir aquí. Fai copy2. Nós imos ampliar e realizar copy2.
Eu estou indo a escribir Ola en letras minúsculas, e de feito eu fico minúsculas Ola como o orixinal
pero o capital Ola a copia.
Pero eu non estou preparado aínda. Eu teño que facer unha última cousa aquí.
46 e 47 é claramente liberar memoria, pero o que iso realmente significa?
O que estou facendo, pensas que, chamando liña 46 e liña 47?
Cal é o efecto que isto ten? Si
[Resposta do alumno inaudível] >> Exactamente.
>> Está só dicindo o sistema operativo, hey, grazas por esta lembranza.
Agora podes usalo para outra persoa.
E aquí está un exemplo perfecto de valores de lixo.
Acabo de utilizar esta memoria para escribir a palabra Ola en 2 lugares,
aquí, aquí, aquí e aquí.
Polo tanto, este é H-e-l-l-o-\ 0.
Pero, entón, eu chamo de liña 46 e liña 47, e vostede sabe o que pasa alí en termos de imaxe?
En realidade, esperar, esta foto é a antiga.
Unha vez que a copia, este cara é realmente apuntando aquí,
entón imos eliminar os números e só abstraerse como as nosas frechas novo.
O que pasa na foto cando eu chamo libre?
[Resposta do alumno inaudível] >> Nin sequera.
Se eu conectar de balde en S e T - un tipo de pregunta capciosa - esta imaxe non cambia en nada
porque chamar s e chamando t só di ao sistema operativo,
hey, pode utilizar esa memoria de novo, pero iso non cambia iso nulo
ou algún carácter especial, non cambiar isto,
iso non cambia o H ou o correo ou o l ou l ou en calquera lugar a calquera outra cousa.
En termos de imaxe, tan pronto lle chame gratis cambios, nada.
E é aí onde reside a orixe de valores de lixo porque se eu, máis tarde, no programa
pedir ao sistema operativo para máis de memoria con GetString ou malloc ou algo parecido
eo sistema operativo, di, por suposto, eu teño 12 bytes de memoria só liberados,
usalos, que é o que vai ser entregado?
Vai ser entregado unha peza de memoria que normalmente deseñar
con puntos de interrogación, pero o que son eses puntos de interrogación?
Eles acontecen ser h-e-l-l-o, h-e-l-l-o.
Estes son os nosos valores de lixo novos para que liberar a memoria.
>> Hai un mundo real implicación aquí tamén.
Isto acontece que ver con memoria RAM, pero os seus ordenadores
realmente facer a mesma cousa co disco.
Nós imos falar sobre iso en particular con un conxunto de problemas futuros que incide sobre forense.
Pero o que realmente acontece se ten algún arquivo confidencial financeira no seu escritorio
ou algún JPEG esbozado e arrastralo ata o seu lixo,
o que ocorre cando arrastralo lo para o lixo ou lixo?
Sabía o que eu estaba falando. [Risas]
O que acontece cando arrastrou que a evidencia na súa lixo ou lata de lixo?
[Resposta do alumno inaudível]
Ben, entón coidado. O que acontece cando fai isto?
A resposta curta é nada, non?
Arquivo multimedia ou sensibles aínda está só sentado nalgún lugar no seu disco duro.
A maioría de nós, polo menos, aprender do xeito máis difícil que precisa baleirar seu lixo
ou a súa lixo para realmente borrar arquivos.
E, de feito, cando prema co botón dereito ou faga clic na súa lata de lixo
Lixo ou escoller Arquivo, baleiro ou o que quere
e realmente baleirar a lata de lixo ou lixo, o que realmente acontece a continuación, para esta imaxe?
Máis nada. Polo tanto, nada realmente acontece no disco.
>> E se nós só temporalmente divagar e escribir - eu só usar a parte de atrás do presente.
Entón, agora a historia está cambiando de RAM, que é onde existen programas
mentres está executando-os para o disco, que é onde se almacenan a longo prazo
mesmo cando o poder sae, polo de agora - e nós imos voltar a iso no futuro -
imos finxir que isto representa o interior do disco duro do seu ordenador
porque para atrás no día adoitaban ser discos circulares, así como disquetes.
Entón, se ten algún arquivo de Excel sensible, pode levar ata este anaco de memoria
no disco do seu ordenador, e eu estou só debuxando 1s e 0s mesmo arbitrario.
Cando arrastra o ficheiro como que a súa lata de lixo ou lixo,
literalmente nada acontece porque a Apple e Microsoft simplemente decidiu
a lata de lixo e lixo é realmente só un espazo reservado temporal.
Quizais, finalmente, o sistema operativo ha baleiralo-la para ti, pero, normalmente, non fai nada,
polo menos ata que estea realmente con pouco espazo.
>> Sen embargo, cando vai para o lixo baleiro ou lixo baleira,
Do mesmo xeito, nada acontece con esta imaxe.
Todo o que acontece está noutro lugar no seu ordenador, hai algún tipo de mesa.
É como unha especie de folla de fraude pouco que di que imos dicir, RESUME.DOC,
para que o seu currículo nun arquivo de Microsoft Word vivía no lugar 123 no seu disco duro,
non na memoria e non na memoria RAM, pero no seu disco duro,
e as súas vidas esbozado JPEG con 456, eo seu arquivo de Excel vive en 789 ou en calquera lugar.
Ao eliminar ficheiros por realmente baleirar o lixo ou lixo,
ese cadro non cambia. Os 0s e 1s no seu disco duro non van a sitio ningún.
Pero este cadro, este banco de datos pouco de sorte, fai a mudanza.
Cando eliminar o seu currículo, é coma se o ficheiro é borrado nalgún sentido,
pero todo o equipo fai é esquecer de onde esa cousa vive no seu disco duro.
Os 0s e 1s que compoñen o seu currículo ou calquera destes outros arquivos aínda están intactos.
>> Entón, se fixo iso accidentalmente, aínda hai unha probabilidade non cero
que pode recuperar os seus datos usando o Norton Utilities ou algún software comercial
cuxo obxectivo de vida é atopar 0s e 1s que tipo de orfas,
esquecido aquí, pero deixaron aquí, de modo que pode obter os seus datos de volta.
Ou investigadores forenses coa policía ou o FBI tería realmente ter un disco duro
e realmente ollar para os patróns de 0s e 1s que mirar como JPEGs, ollar como arquivos de Excel,
e recuperala los desa forma, aínda que o ordenador teña esquecido alí.
Entón o único xeito realmente para eliminar datos, como discutir no futuro,
é esfregar ou limpar o ficheiro ou disco duro -
Realmente non pode se librar do 0s e 1s
porque senón ía comezar con unha unidade de gigabytes
e acabar con unha unidade de megabyte difícil se constantemente borrar,
literalmente, 0s e 1s.
Entón, o que faría se realmente quería para cubrir os seus rastros
e que o problema fundamental é que aínda hai 0s e 1s no disco?
Eu vexo alguén gesticulando que fisicamente romper o dispositivo. Que ha traballar.
[Risas] Pero, se ese é o tipo de unha solución cara, o que sería máis razoable?
Si >> [Alumno] substitúe-los. >> Substitúe-los co que? >> [Estudante] Outros datos.
Outros datos. Pode simplemente substituír o disco con 0s ou 1s ou todos os 0s, todos os 1s.
>> E iso é de feito o que algúns dos programas fai.
Podes mercar o software ou mesmo obter o software libre,
e mesmo construído en Mac OS estes días, menos en Windows,
é a capacidade de borrar con seguridade.
En realidade, se quere todos os home run hoxe, se ten un Mac e facelo,
se ten algo na súa lata de lixo, pode facer Baleirado Seguro do lixo,
que fai exactamente iso.
En vez de borrar arquivos só aquí, iso non elimina o aquí 0s e 1s,
ao contrario, ela só cambia todos eles, por exemplo, para 0s e punto, punto, punto.
Entón, un dos seus futuros serie de exercicios será realmente intencionalmente recuperar datos -
fotografías que sacou de persoas, lugares e cousas no campus
para o cal imos facer unha imaxe forense de unha tarxeta de memoria da cámara dixital,
que é a idea mesma - e vai ter que ser reto a realmente atopar
os patróns que representan JPEGs no seu disco duro,
moi parecido ao ex-alumno, cuxo correo electrónico que lin hai unhas semanas fixo
para recuperar fotos da súa irmá.
Por que non facemos un intervalo de 5 minutos aquí, e nós imos reagrupar con máis memoria.
Entón é aquí que as cousas están un pouco alucinante, pero este é un paso moi poderoso
para a comprensión de todo isto o máis.
Aquí está un programa chamado pointers.c.
É entre código de hoxe mostra.
Teña en conta que en primeiras liñas, 19 a 22, todo o que estamos facendo é algo así como GetString
e retornando un enderezo, almacenando-o s.
De agora en diante para pset mesmo 3 se quere, pero pset 4 e no
onde podes comezar a tomar esas Rodas pequenas mesmo,
non hai razón para finxir que as cordas existe máis.
É certamente bo para só comezar a dicir * char.
>> Como un aparte, en referencias en liña e en libros moitas veces se pode ver a estrela ao lado da variable.
Podes incluso ver os espazos en torno a ambos os dous lados.
Todas estas son funcionalmente correcta.
De momento, porén, imos padronizar esa visión para facer super claro
que char * é como dicir punteiro personaxe.
Isto é o tipo de datos.
E, a continuación, o nome da variable é s no presente caso.
Entón, nós temos tido unha corda e chamamos el s.
E entón aquí notar que eu estou facendo en realidade, un pouco de malandragem.
Iso é chamado de aritmética de punteiro, que é unha especie de super sinxelo.
Significa só sumar e restar números para punteiro.
Pero isto realmente funciona.
Este programa imprime o carácter aparentemente cadea 1 por liña de tal forma que o resultado final -
Só así podemos romper onde iso vai dar, facer punteiros, punteiros correr, deixe-me facer zoom in
Agora déixeme escriba algo como OLA e escriba Intro
e imprime un carácter por liña.
Ata un segundo atrás, tería feito isto coa notación de colchete.
Teriamos un loop e nós fariamos printf de s [i] e nós faría iso de novo e de novo e de novo
coa n invertida ao final de cada liña.
Pero este programa é distinto. Este programa está a usar, literalmente, aritmética.
Entón, o que está a suceder aquí?
Primeiro de todo, antes deste ciclo é executado, o que, só para quedar claro, é realmente s?
S é? >> [Alumno] Un enderezo. >> Este enderezo.
>> E é o enderezo, no caso de Ola, o primeiro carácter en que a palabra, que é h.
Entón s, neste exemplo particular, o seu enderezo de h.
Entón, o que iso significa para facer s + i?
Ben, eu comeza en 0 neste loop. Nós fixemos moitas veces que.
Eu está indo a ir ata a lonxitude da corda, aparentemente.
Así, na primeira iteração do loop, i é, obviamente, 0.
Polo tanto, esta expresión está dicindo s + i - en vez diso, s +0--que é, obviamente, só s.
Entón, o que é * s aquí?
Agora estamos usando a estrela dunha forma lixeiramente diferente.
Deixe-me ir adiante e se librar de t, porque estamos falando de t feito e copias de s.
Agora só quero contar unha historia envolvendo s.
E por iso, neste momento, despois de tipo cadea, o noso mundo parece moi como facía antes
s con só almacenar o enderezo de h e, máis xeralmente apuntando para a cadea Olá
Se eu agora facer unha liña como * (S + i), imos tentar iso.
Entón * (S + i). Deixe-me simplificar isto porque este é 0, que é * (s 0).
Ben, agarde un minuto. Simplificar aínda máis. Este é * (s).
Ben, agora os parénteses son unha especie de idiota, entón agora imos facer * s.
Así, na primeira iteração do loop, que a liña que está en destaque, 26,
é moi fermoso equivalente a imprimir este.
Cal é o tipo de datos * s?
Neste contexto, unha vez que a estrela pasa a ser parte de ti s,
pero, máis especificamente, porque xa non estamos declarando s,
non estamos creando unha variable máis, non hai ningunha mención de char * na liña 26,
non hai ningunha mención da cadea palabra clave, estamos usando só unha variable chamada s,
verifica-se agora a estrela ten un pouco diferente e, reconhecidamente, confundindo significado.
* S, aquí, significa ir ao enderezo en s e imprimir o que está aí.
Entón s aquí, * s - algo así como ramplas e escaleiras, siga a frecha - aquí.
Polo tanto, esta é * s.
>> Entón, o que é impreso na primeira iteração do loop de que na liña 26?
Eu imprimir% c, que é o espazo reservado para un personaxe,
a continuación, un \ n para unha nova liña. * (S + i) onde i é 0 é só iso.
Entón, o que de char que eu poñer en para c%? H.
Na próxima iteração do loop - probablemente pode ver onde iso vai dar -
a próxima iteração i é, obviamente, un, entón iso significa 1,
e entón agora eu teño dos parénteses porque agora a estrela que dicir
ir ao enderezo de memoria de 1.
O que é s? Imos voltar no tempo e dicir esta frecha agora non está realmente facendo-nos os favores.
Imos, máis especificamente, dicir que este é almacenar o número 123
porque o comezo desta cadea Ola, este é o enderezo 123, este é 124, e así por diante.
Entón, na segunda iteração cando estou dicindo 1, que é como dicir que un 123,
tamén coñecido como 124, entón o carácter é impreso na segunda iteração?
E no enderezo de memoria 124.
Entón + novamente, 125, 126, 127, e este lazo sorte deixar antes de chegar aquí
porque eu estou usando strlen para estar seguro de que eu non conta moi alta.
Entón, iso tamén é iso.
De novo, iso é como se tivésemos feito unha semana.
Deixe-me escribir na liña de abaixo aínda que nós non queremos facer os dous.
Isto é idéntico a este momento.
>> Así, aínda que s é unha cadea, como estamos chamando el por semanas, s é realmente un char *.
Entón, se queremos ser anal super, é realmente correcta de escribir o carácter específico
no lugar Ith utilizando estes enderezos numéricos e este operador estrela,
pero, francamente, este é máis limpo tanta cousa. Entón iso non é malo.
Non hai razón para deixar de facer liña 27 aquí, pero 26 é funcionalmente o mesmo,
e é funcionalmente o mesmo para exactamente as razóns que estamos discutindo ata agora.
E, por último, 29 e práctica só bo.
Chamando libre s significa que agora está dando de volta a memoria que lle deu GetString
porque unha vez máis, como mencionei luns, GetString de semana
foi a introdución dun erro no seu código.
O seu código de semana tivo derrames de memoria
polo cal foi preguntando GetString para a memoria, pero nunca foi dándolle de volta.
E que foi deliberadamente elixido por nós pedagoxicamente
porque é moi pouco para pensar no inicio.
Pero agora necesitamos máis simetría.
Pedir ao ordenador para a memoria, como é o caso para GetString,
como é o caso, ao parecer para malloc,
Debe agora pset diante 4 tamén calquera memoria libre tal.
Teña en conta que isto é diferente de dicir n int.
Non precisa liberar iso porque non chamou GetString
e non chamar malloc.
>> E mesmo se chamou GetInt como vai finalmente ver
GetInt non aloca memoria para ti, porque realmente pode pasar ao redor de números enteiros
e coches alegóricos e chars só a forma como temos benvida a facer para a semana.
Cordas, pero é especial porque realmente son a concatenação de caracteres múltiples.
Entón, eles están só diferente de caracteres e coches alegóricos e ints e similares.
Pero imos volver ao que antes do tempo.
Algunha preguntas, entón neste inicio de punteiros? Si
[Pregunta estudante inaudível]
Ah, boa pregunta.
Unha das poucas cousas que realmente C fai para ti, o que é conveniente,
é el descobre para o que é o tamaño do tipo de datos
e despois fai ese tipo de multiplicación para ti.
Isto é irrelevante no caso de caracteres, porque case sempre é char a 1 byte,
entón isto funciona.
Pero, por mor da discusión, se está realmente imprimir enteiros
e estaba tentando imprimir algúns o valor que estaba apuntando a un número enteiro,
vostede da mesma forma non tería necesidade de facer + 4 * i só porque un int é de 4 bytes.
Aritmética de punteiro significa que o compilador C e facer toda a matemática que para ti.
Todo o que ten que se preocupar é a conta nunha especie de sentido humano. Si
[Estudante] Se declarar unha secuencia dentro dun loop for, ten que liberar-lo despois?
Boa pregunta.
>> Se declarou unha corda dentro do loop for, precisa liberalo lo máis tarde?
Só ten memoria libre que reservar con GetString ou malloc.
Entón, se acaba de dicir algo así como - deixe-me poñer chaves agora así todo o código está relacionado.
Se fixo algo, aínda que buggily, como este, char * t = s,
non necesita de t libres, porque t non implica ningunha mención de malloc ou GetString.
Se, pola contra fixo iso, GetString, entón si, ten que t libres.
E, de feito, a súa única oportunidade de facelo é agora dentro deste lazo, para o mesmo problema de ámbito
que temos discutido no pasado.
Se non, sería a distribución de memoria, distribución de memoria, distribución de memoria,
e ao final do programa, porque está fóra dese circuíto,
t non existe, pero nunca contou o sistema operativo
que non precisa máis que a memoria.
E en pouco tempo, para pset 4 ou 5 imos equipa-lo con un programa chamado Valgrind,
que é semellante en espírito a GDB no que ten un pouco de unha interface arcano,
pero o seu propósito na vida é axudar.
E Valgrind é un programa que, no futuro, buscar os seus programas
buscar vazamentos de memoria, sexa de GetString ou malloc,
que nós imos comezar a usar todo o máis que deixar de usar a biblioteca CS50 tanto.
Finalmente agora temos un tipo do vocabulario e do tipo de modelo mental na teoría
co cal se resolve este programa roto.
>> Polo tanto, neste programa roto, intercambio funciona dentro de intercambio,
pero nunca traballou realmente no inicio porque principal pasou x e y, recall,
e os que foron aprobados en por valores, por así dicir.
Copias deles foron dados para intercambiar.
Ata o final de intercambio, a e b realmente fora trocado,
pero está claro que X e Y, como vimos o luns, non fora.
Entón propoño en verde aquí que esta é realmente a solución aquí.
E, de feito, deixe-me pasar miñas estrelas só para ser coherente
a pesar de, de novo, funcionalmente, iso non importa.
As semanas futuros imos explicar cando e por que isto importa.
Entón en verde agora é unha solución.
Francamente, parece un monte máis confusa, porque eu teño todas esas estrelas.
Deixe-me apuntar unha única cousa.
A liña de arriba aquí onde di int * a * b e int
é fundamentalmente facer a mesma cousa que el sempre ten.
É declarar que dous argumentos ou parámetros para intercambiar,
a primeira das cales é un punteiro int chamado,
a segunda das cales é un punteiro int chamado b.
O único que hai de novo neste punto é o feito de que hai unha estrela alí.
>> O que significa isto? A non é un int, b non é un int.
Un é o enderezo dun int b é o enderezo dun int diferente.
Aquí, é aquí que eu admite C queda confuso.
Agora estamos a usar unha estrela, pero ten significado distinto neste contexto.
Porque nós non estamos declarar punteiros como estamos aquí,
aquí estamos dereferencing cousas.
Entón, tecnicamente, a estrela neste contexto de primeira liña, segundo e terceiro dentro de intercambio
é o operador dereference, o que significa só ir alí.
Así como o meu dedo seguiu a frecha para h,
* Un medio ir a este enderezo e me pensar o int que está aí.
* Significa que B vaia ao enderezo e pasar-me o que está aí.
Entón, imos redesenhar a imaxe de luns usando agora unha pila de cadros,
o fondo do cal vai ser principal,
a superior das cales será de permuta,
para que o noso mundo mira, así como luns, coma este.
Aquí é unha peza de memoria principal é que vai empregar.
>> Teña en conta que de luns que o programa só tiña dúas variables,
un chamado x e y un chamado, e eu tiña colocado os números 1 e 2 alí.
Agora, cando eu chamo intercambiar como eu fixen o luns,
anteriormente, cando eu usei a versión vermella deste programa, que se parece iso,
Eu teño dous parámetros, A e B, eo que escribir aquí e aquí?
Só 1 e 2, literalmente copia de x e y.
Hoxe cambiar isto.
Hoxe, en vez de pasar ints a e b, imos pasar dous enderezos.
Estes enderezos ocorrer para apuntar para ints, pero estes enderezos non son ints si.
Son enderezos. É como un enderezo postal vez.
Entón agora necesitamos só dar a min mesmo un pouco máis detalladamente sobre a pantalla.
Esta é a memoria do meu ordenador como foi todo o día.
Agora necesitamos algún esquema de numeración arbitraria.
Entón imos só dicir que, só por casualidade, que este é o enderezo de memoria 123, 124.
Nós só dicir que este é 125, que é 126, e así por diante, pero iso é totalmente arbitrario.
Nós só necesitamos algún esquema de numeración na miña memoria.
Entón agora cando realmente pasar x e y, eu non vou pasar x e y;
Vou pasar o enderezo postal, por así dicir, de x e y
de xeito que o que queda almacenado aquí e aquí non é 1 e 2,
pero se pode ver o meu pequeno texto, que é pasado aquí e aquí?
[Resposta do alumno inaudível] >> Exactamente. 123 e colocar aquí e 124 colócase aquí.
>> Agora, porque eu usei a estrela deste xeito primeira liña aquí enriba,
meu programa só sabe que 123 e 124, a pesar de seren, obviamente, enteiros
que calquera humano podería notar, eles deben ser interpretados como enderezos, enderezos numéricos.
Eles non son en si mesmas ints, son enderezos,
e iso é porque eu explícitamente pon as estrelas alí.
Entón agora na miña liña primeiro, segundo e terceiro do código real que pasa aquí?
Imos deseñar o resto da imaxe.
Tmp é exactamente como era o luns. Nada de especial sobre tmp.
É só un lugar de 32 bits variable, e dentro do que eu estou aparentemente almacenar o valor dun ficheiro *.
Agora, se eu só dixen tmp = a, o que poñer aquí? >> [Alumno] 123.
123. Pero iso non é o que eu estou facendo.
Eu estou dicindo tmp = * a. Significa estrela ir alí.
Entón aquí vai unha, 123. Como podo ir alí? Finxir que non hai unha frecha.
Ben, aí está, 1. Entón, o que está almacenado en tmp, aparentemente? Só 1.
Polo tanto, noutras palabras, é tmp * a *, un medio ir ao enderezo que está actualmente nunha,
que aparentemente é 123.
>> Ok, aquí estamos na posición 123, eu vexo o número 1,
entón eu vou poñer o número 1 alí.
Agora o que fago na liña 2, a * = * b?
Este é un pouco máis complicado, porque agora o que é un? É 123.
Entón, a * é onde? Exactamente onde eu estaba antes. Entón, vai alí. Okay.
Agora, por fin, e entón finalmente iso vai comezar a ter sentido, espera-se,
* B significa que está en b? 124. Entón eu teño ir alí, que é 2.
Entón, o que podo poñer onde?
2 entra aquí, porque vai * b * a. Entón, eu vou facer iso.
E xa pode ver, se cadra, de que estamos moito máis preto
Para solucionar este problema, estúpido simple correctamente por primeira vez
porque agora nós aínda temos un recordo do que foi x,
temos dúas copias, reconhecidamente, de y,
pero a liña 3 agora di * b.
Entón aquí está b. * B medios para alí. Entón, onde é o lugar 124?
É aparentemente aquí. Entón o que eu poñer aquí? Obviamente tmp.
Entón agora eu fago iso. Entón, eu teño unha aquí e 2 aquí.
E agora o que dicir de todo isto, o 123, o 124 eo 1?
Así que retorna de intercambio, esa memoria é tan bo como perdido
porque así como o retorno de intercambio, o sistema operativo
é libre para usar a memoria de novo no futuro.
Só a memoria principal, na parte inferior desta pila de chamada varas en torno.
>> E así finalmente temos agora unha versión de traballo.
Deixe-me ir swap.c, e observe o seguinte.
No cumio do programa que eu mudei o meu prototipo para ser int * a * b e int.
Así, a única cousa que cambiou para ir de vermello, o que foi malo para o verde, que é bo,
é que eu engade estas estrelas de hoxe.
Pero, entón, aquí no propio intercambio eu tiña que copiar, pegar o que era só no slide.
Eu teño unha estrela aquí, estrela aquí - que coincide co prototipo -
e despois de todas estas cousas agora ten estrelas, excepto para tmp
porque o uso dunha variable temporal, non hai nada novo nisto.
Eu só teño de almacenamento temporal para un int.
Entón, nós non necesitamos unha estrela alí.
Nós só necesitamos unha estrela, para que poidamos atravesar este tipo de límite arbitrario
entre estes dous cadros na memoria do meu ordenador.
Pero unha última cousa que ten que cambiar, e pode ter hano descifrar xa.
O que outra liña é obviamente diferente agora? >> [Alumno] e x.
>> Si, entón 25 é a última liña de código que eu teño cambiar para que isto funcione.
Unha semana, e mesmo o luns da liña 25 quedou así, cambiar x e y,
e este foi só rota porque se di de intercambio (x, y)
está dando copias de X e Y para intercambiar, entón está facendo a súa cousa,
pero nunca está realmente cambiando X e Y si.
Así, mesmo se nunca viu este personaxe antes co comercial no código,
só dar un palpite. O que fai o comercial facer, aparentemente?
[Alumno] e enderezo. >> Toma o enderezo.
Así, o comercial está dicindo me dar o enderezo de x.
Quen sabe onde é? El pasa a ser 123. Eu non me importa. Só me dea o seu enderezo de x.
& Y significa darme o enderezo de y.
E nese punto a historia é perfectamente consistente coa imaxe que deseñou un momento atrás.
>> Entón, eu vou admitir punteiros, certamente para min, cando eu empecei a aprender iso,
foron sempre unha das cousas máis difíciles de implicar miña mente.
Pero entender, especialmente a medida que continuar a xogar con eses tipos de cousas,
se decompô-lo para este tipo super sinxelo de intelectualmente desinteressante problemas
só movendo en torno de números, a resposta a unha gran confusión con punteiros
realmente pode ser obtido a partir destes mecánica moi básicas.
Aquí está o enderezo. Vaia coa estrela.
Ou, inversamente, aquí está un e comercial. Descubrir o que o enderezo realmente é.
Todo ben.
Entón, onde está toda esa memoria vén?
Poñemos esta imaxe dun par de veces, e eu sigo prometedor imos volver a el,
pero aquí é a representación da memoria do seu ordenador
que é un pouco máis marcado que o noso cadro aquí é.
O segmento de texto na parte superior representa o que se refire ao seu programa?
[Resposta do alumno inaudível] >> Desculpa? Diga novo.
[Alumno] O programa real. O programa >> real.
>> Así, o Clang 0s e 1s que teña compilado despois de escribir código C e en seguida, executando
e xerando extremos 0s e 1s por estar escondido alí na memoria
porque cando dobre clic nun icono no seu Mac ou PC
ou executar un comando como Mario no seu poder, o seu 0s e 1s do disco
son cargados na memoria para que o ordenador poida manipulala los
e executa-los máis rapidamente.
Datos para inicializados e os datos non inicializados, non imos falar moito sobre aqueles,
pero estas son só variables globais.
Inicializar significa variables globais que deu valores;
non inicializar significa variables globais que aínda non dan valores.
Despois, hai as variables de ambiente que eu vou completamente a miña man a onda,
pero eles están alí e que almacena cousas como o seu nome de usuario
e outro tipo de detalles de nivel inferior.
Pero os máis suculentos anacos de esquema da súa memoria é esa cousa chamada a pila eo heap.
A pila de novo, para ser claro, é a memoria que se usa sempre que funcións son chamadas,
sempre que haxa variables locais
e sempre que hai parámetros que están sendo repassados.
Todo o que acontece na pila.
A pila non temos falado, pero dar un palpite que usa a pila.
Só unha peza diferente de memoria.
El pasa a ser feita aquí enriba, pero iso é unha convención arbitraria pictórica.
Que aparentemente estaba usando a memoria da pila de semana?
É tecnicamente ti, pero indirectamente. >> [Alumno] GetString.
GetString e malloc. Entón aquí está a diferenza fundamental.
>> Vostede sabe para as últimas semanas que se precisa de memoria, pode declarar unha variable.
Se precisa de moita memoria, declarar unha matriz dereito dentro da súa función.
Pero o problema que enfrontamos é mantido se declarar variables locais dentro de funcións,
logo que o retorno da función, o que pasa coa memoria e aquelas variables?
Só o tipo de que non é máis o seu, non? El simplemente desaparece tipo de conceptualmente.
Aínda é fisicamente alí, obviamente, pero non é o seu dereito de uso.
Esta é, obviamente, un problema se quere escribir funcións na vida
que realmente reservar memoria e non devolve-lo inmediatamente.
Caso en cuestión: GetString propósito na vida é non ter idea de antelación
como gran dunha corda Eu vou escribir no teclado,
pero ten que ser capaz de reservar memoria para almacenar David ou Ola
ou ensaio un todo que o usuario pode ter ingresaran dentro
Entón GetString vén usando malloc.
Malloc, polo tanto, non debe estar usando a pila;
en vez diso, está a usar esa cousa chamada heap.
Non hai nada diferente sobre a memoria. Non é máis rápido ou máis lento ou algo así.
É só fisicamente nun lugar diferente.
>> Pero a regra é que a memoria que está alocada na pila
nunca ser tirado de ti ata que chamar - dar un palpite - libre.
Por outra banda, calquera memoria que pedir na pila por só declarar unha matriz
ou declarar unha variable como temos benvida a facer para a semana,
que, por defecto acaba na pila.
E que funciona 90% gran parte do tempo, pero nesas ocasións máis raras
onde quere reservar memoria e mantelo por preto,
entón tes que usar unha función como malloc.
Ou usamos unha función como GetString, que á súa vez usa malloc.
Imos ver onde isto pode romper e, a continuación, dar un ollo ao Binky.
Nós imos voltar a iso no futuro.
Aquí está o programa super simples que nos primeiros 2 liñas fai o que?
En inglés, o que esas 2 primeiras liñas de código facer dentro principal?
[Resposta do alumno inaudível]
Coidado. Non me dá o enderezo de x ou y.
[Estudante] da punteiros para ints. >> Boa. Déame dous punteiros para enteiros.
Noutras palabras, dáme dous anacos de memoria que gardo deseño de hoxe,
aínda que eu apaguei o momento, como cadrados.
Déame dous anacos de memoria, un chamado x, y un chamado -
antes eu chamaba S e T - e cal é o tipo de que anaco da memoria?
Vai para almacenar un enderezo.
É de * tipo int.
>> Así, o enderezo dun int ha eventualmente viven en x,
o enderezo de un int acabará por vivir en y,
pero, inicialmente, o que está dentro de X e Y? Quen sabe? Valores de lixo.
Non ten nada que ver con punteiros.
Se non poñer algo alí, quen sabe o que realmente está aí?
Agora, x. O que pasa aquí? Isto é legal agora porque x é un punteiro. É un int *.
Entón iso significa que podo poñer en X o enderezo de algún anaco de memoria.
O que malloc voltar? Perfecto, el retorna enderezos,
o enderezo do primeiro byte dun bloque enteiro de memoria.
Cantos máis é o que parece atribuír, por exemplo, no interior do aparello?
Cal é o tamaño dun int? 4.
Se pensas que volta para unha semana, non é super importante sempre lembrar que,
pero, neste caso, é útil saber, 4 bytes.
Polo tanto, este é reservar na pila 4 bytes
e é o enderezo de retorno da primeira para me arbitrariamente.
Agora, o que está facendo x?
A * x = 42 está facendo o que?
Neste punto da historia que temos x, que se parece iso con algún valor de lixo,
este é agora y con algún valor de lixo, agora na liña 3 eu alocados 4 bytes.
Esta imaxe esencialmente coma este.
Ou, máis especificamente, esta é arbitraria enderezo 123, iso é o que a nosa historia agora parece.
* X = 42 agora significa o que? Isto significa ir ao enderezo 123 e poñer o número 42 alí.
Eu non teño chamar a estas liñas, porque nós non estamos facendo cordas.
>> Eu debería ter escrito así, e só por mor da manifestación, o
42 como unha especie de int ocupa moito espazo, 4 bytes.
Entón, iso é o que pasou alí, pero hai un problema.
* Y = 13. O que vai ocorrer aquí?
O problema é * y no noso mundo simplificado significa só ir ao enderezo en y.
O que está en y? É un valor lixo.
Entón, imos supor que ese valor de lixo e 5551212, algo tolo así.
Medio * y ir para abordar 5551212.
Isto é como aquí. Non hai, por exemplo.
Entón * y recibe 13 significa que eu estou tentando facer 13 aquí. El non existe.
Eu xa superou o segmento do cadro negro. O que eu ganancia?
Esta fallo de segmento enigmática mensaxe porque eu estou tentando poñer na memoria
un valor como 13 nun lugar que non existe.
O resto do programa pode funcionar ben, pero ata que punto isto non acontece.
Entón, imos tentar contar esa historia.
Nós imos voltar a que, unha vez que falamos de feitizo.
Imos volver a este e completar con esa cousa chamada Binky,
que recall é un profesor de Stanford sentado na casa xogando con claymation,
para contar a historia exactamente do programa que mesmo.
É só uns 3 minutos de duración. Aquí temos Binky.
[Orador masculino en vídeo] Hey Binky, acorda. É hora de diversión punteiro.
[Binky] O que é isto? Máis información sobre punteiros? Ah, bo!
[Orador masculino] Ben, para comezar, eu creo que nós imos ter un par de punteiros.
>> [Binky] Okay. Este código aloca dous punteiros que poden apuntar para números enteiros.
[Orador masculino] Okay. Ben, eu vexo os dous punteiros, pero eles non parecen estar a apuntar cara algo.
[Binky] Iso mesmo. Inicialmente, os punteiros non ligan con nada.
As cousas que eles apuntan son chamados pointees, e configuralo los é un paso separado.
[Orador masculino] Ah, non, non. Eu sabía. Os pointees son separados.
Er, así como reservar un pointee?
[Binky] Okay. Este código aloca un novo pointee enteiro, e esta parte define X para apuntar para el.
[Orador masculino] Ei, iso parece mellor.
Entón el facer algo. >> [Binky] Okay.
Vou cancelar o punteiro X para almacenar o número 42 na súa pointee.
Para este truco eu teño da miña varinha Magic da dereferencing.
[Orador masculino] A súa varinha Magic de dereferencing? Isto é óptimo.
[Binky] Isto é o que o código parece. Eu só vou definir o número e ... [Premendo son]
[Orador masculino] Ei, mira, aí vai.
Entón, facendo un dereference en X segue a frecha para acceder a súa pointee,
neste caso para almacenar 42 en alí.
Ola, tente usalo para almacenar o número 13 ata o outro punteiro, y.
[Binky] Okay. Vou pasar por riba aquí para y e obter o número 13 configurar
e despois tome a vara de dereferencing e só ... [Zumbido] Whoa!
[Orador masculino] Oh, hey, iso non funcionou.
>> Diga, Binky, eu non creo que dereferencing y é unha boa idea
que a configuración da pointee é unha etapa separada
e eu non creo que xa fixen iso.
[Binky] Hmm, bo punto.
[Orador masculino] Yeah. Alocamos o punteiro y mais nunca configuralo para apuntar para unha pointee.
[Binky] Hmm, moi observador.
[Orador masculino] Ei, está parecendo bo alí, Binky.
Pode resolve-lo, de modo que y apunta para o pointee mesmo que x? >> [Binky] Claro.
Vou usar a miña varinha Magic de atribución de punteiro.
[Orador masculino] é que vai ser un problema como antes?
[Binky] Non, iso non toque nos pointees.
Só cambia un punteiro para apuntar para o mesmo que o outro. [Premendo son]
[Orador masculino] Oh, eu vexo. Agora y apunta para o mesmo lugar que x.
Entón, agarde. Agora y é fixo. Ten un pointee.
Entón podes probar a varinha de dereferencing novo para enviar a máis de 13.
[Binky] Uh, todo ben. Aquí vai. [Premendo son]
[Orador masculino] Ei, mira iso. Agora dereferencing obras sobre y.
E porque os punteiros están a compartir que pointee un, dous ver 13.
[Binky] Si, compartir. Calquera que sexa.
>> Entón, imos cambiar de lugar agora?
[Orador masculino] Oh mira, nós estamos fóra do tempo. >> [Binky] Mais -
[Orador masculino] Basta lembrar as tres regras de punteiro.
Número 1, a estrutura básica é que ten un punteiro que apunta máis a un pointee.
Pero o punteiro e pointee son separados, e do erro común é a creación dun punteiro
pero esquecerse de darlle un pointee.
Número 2, dereferencing punteiro comeza o punteiro e segue a súa frecha sobre
para acceder a súa pointee.
Como todos sabemos, iso só funciona se hai un pointee,
que tipo de volver gobernar o número 1.
Número 3, a asignación dun punteiro punteiro asume e cambia-
para apuntar para o mesmo pointee outro punteiro.
Así, tras a concesión, os dous punteiros apuntan para o pointee mesmo.
Ás veces iso é chamado de reparto.
>> E iso é todo o que hai para realmente. Bye-bye agora.
Este é Binky. Este é CS50. Imos ver a próxima semana. [Aplausos]
>> [CS50.TV]