[Música tocando]
>> DOUG LLOYD: OK, então uma sugestão antes de iniciar aqui.
Se você ainda não assistiu o vídeo em dicas que você pode querer fazê-lo em primeiro lugar.
Porque este vídeo é outra forma de trabalhar com ponteiros.
>> Por isso, vai falar sobre alguns conceitos
que cobrem no Indicadores de vídeo, e estamos
vai passar por cima deles agora, supondo que eles já estão
tipo de entendido.
Então, isso é apenas o seu aviso justo que, se você está vendo este vídeo
e você ainda não viu o vídeo ponteiros, pode tipo de
voar sobre sua cabeça um pouco.
E por isso talvez seja melhor para vê-lo nessa ordem.
>> Então, nós já vimos um maneira de trabalhar com ponteiros,
que é nós declaramos um variável, e então nós
declarar outra variável, um ponteiro variável, que aponta para ele.
Então nós criamos um variável com um nome, nós temos
criada uma segunda variável com um nome, e apontamos que a segunda variável
em que em primeiro lugar.
Este tipo de tem um problema, porém, porque
obriga-nos a saber exatamente a quantidade de memória que estamos
vai precisar do momento nosso programa é compilado.
>> Por que é que?
Porque temos de ser capazes de nomear ou identificar todas as possíveis variáveis
poderíamos encontrar.
Podemos ter uma matriz que pode ser capaz de manter uma grande quantidade de informações,
mas ainda não é exatamente suficientemente precisa.
E se nós não sabemos, E se não temos idéia
o quanto vamos precisar em tempo de compilação?
Ou que se o nosso programa vai executado por um tempo muito longo,
aceitar vários usuário dados, e não podemos realmente
estimar se estamos vai precisar de 1.000 unidades?
>> Não é como nós podemos dizer na linha de comando
inserir quantos itens você acha que vai precisar.
Bem, o que se esse palpite é errado?
Alocação dinâmica de memória tipo de permite-nos a caminho
para contornar este problema particular.
E a maneira como ele faz isso é usando ponteiros.
>> Podemos usar ponteiros para tenha acesso aos dinamicamente
memória alocada, memória que está alocado como o programa está sendo executado.
Não é alocada em tempo de compilação.
Quando você alocar dinamicamente memória se trata de um pool
de memória conhecido como o heap.
Anteriormente toda a memória nós temos vindo a trabalhar com no curso
foi proveniente de uma piscina de memória conhecida como a pilha.
Uma boa maneira de geral manter em regra mente-- e este
nem sempre são verdadeiras, mas praticamente quase
mantém sempre é que qualquer true-- vez que você dá um nome de variável que
provavelmente vive na pilha.
E qualquer hora que você não fazer dar uma variável de um nome,
que você pode fazer com memória dinâmica alocação, ele vive na pilha.
>> Agora eu sou o tipo de apresentar isso como se há essas duas piscinas de memória.
Mas você pode ter visto este diagrama, que é geralmente
uma representação de o que a memória parece,
e nós não estamos indo para se preocupar com tudo o material na parte superior e na parte inferior.
O que nos interessa é esta parte em meio aqui, heap e pilha.
Como você pode ver por olhando para este diagrama,
estes não são, na verdade, dois grupos separados de memória.
É um conjunto compartilhado de memória onde você começa, neste visuais
você começa na parte inferior e começar a encher
a partir do fundo com a pilha, e você começar no topo e começar a encher
de cima para baixo com o heap.
Mas é realmente o mesmo pool, é apenas
spots diferentes, diferentes locais na memória que estão sendo alocados.
E você pode ficar sem memória por um ou outro ter
o heap percorrer todo o caminho para a parte inferior, ou têm
a pilha de percorrer todo o caminho até o topo, ou que tenham a pilha ea pilha
encontrar-se uns contra os outros.
Todos esses podem ser condições que causam o seu programa
para executar com falta de memória.
Portanto, manter isso em mente.
Quando falamos de a pilha ea pilha
estamos realmente falando sobre o mesmo pedaço geral da memória, apenas
diferentes porções de que a memória.
>> Então, como é que vamos chegar dinamicamente memória alocada em primeiro lugar?
Como é que o nosso programa começar memória como ele está funcionando?
Bem C fornece uma função chamada malloc, alocador de memória, o que
você faz uma chamada, e você passar em quantos bytes de memória que você deseja.
Portanto, se seu programa está sendo executado e você quer um tempo de execução inteiro,
você pode Mallock quatro bytes de memória, malloc parênteses quatro.
>> Mallock vai passar por olhando através da pilha,
porque estamos dinamicamente alocação de memória,
e ele vai voltar para você um ponteiro para a memória.
Ele não lhe dá que memory-- não dar-lhe um nome,
dá-lhe um ponteiro para ele.
E é por isso que eu disse de novo que é importante talvez
assistiram o vídeo ponteiros antes de chegar longe demais para isso.
Então malloc vai lhe dar de volta um ponteiro.
>> Se Mallock não posso lhe dar qualquer memória porque você correr para fora,
ele vai lhe dar de volta um ponteiro nulo.
Você se lembra o que acontece se tentar excluir a referência um ponteiro nulo?
Nós sofremos uma falha seg, certo?
Isso provavelmente não é bom.
>> Assim, cada vez que você faz uma chamada para malloc você sempre, sempre
precisa verificar se ou não o ponteiro deu-lhe de volta é nulo.
Se for, você precisa terminar o seu programa porque se você tentar e dereference
o ponteiro nulo você está indo a sofrer uma falha de segmentação
e seu programa é vai falhar de qualquer maneira.
Assim como nós estaticamente obter um inteiro?
>> int x.
Nós provavelmente fiz isso um monte de vezes, certo?
Isso cria uma variável chamada x que vive na pilha.
Como podemos obter dinamicamente um número inteiro?
Int estrela px igual malloc 4.
>> Ou, mais apropriadamente nós diríamos int estrela px
equivale ao tamanho de malloc de int, apenas para jogar um pouco menos
números mágicos em torno do nosso programa.
Isto vai obter para nós quatro bytes de memória do heap,
eo ponteiro chegarmos de volta para ele é chamado px.
E então, assim como nós temos feito anteriormente nós
pode excluir a referência para px acessar essa memória.
Como podemos obter um número inteiro do usuário?
Podemos dizer int x é igual a obter int.
Isso é bastante simples.
E se nós queremos criar uma matriz x de carros alegóricos que vivem na pilha?
flutuar stack_array-- esse é o nome dos nossos colchetes array-- x.
Isso vai criar para nós um array x de carros alegóricos que vivem na pilha.
Podemos criar uma matriz de carros alegóricos que vive na pilha também.
A sintaxe pode parecer um pouco mais complicado,
mas podemos dizer flutuador estrela heap_array igual
malloc x vezes o tamanho do flutuador.
Eu preciso de espaço suficiente para armazenar x valores de ponto flutuante.
Então digo que preciso de 100 carros alegóricos, ou 1.000 carros alegóricos.
Assim, nesse caso, seria 400 bytes para 100 carros alegóricos,
ou 4.000 bytes para 1.000 carros alegóricos, porque cada flutuador ocupa
quatro bytes de espaço.
>> Depois de fazer isso eu posso usar o sintaxe colchete em heap_array.
Assim como eu faria em stack_array, I pode acessar seus elementos individualmente
usando heap_array zero, um heap_array.
Mas recordar a razão que nós podemos fazer isso porque é o nome de uma matriz em C
é realmente um ponteiro para primeiro elemento desse conjunto.
Assim, o fato de que estamos declarando um matriz de carros alegóricos na pilha aqui
na verdade é um pouco enganador.
Nós realmente estamos no segunda linha de código não
também a criação de um ponteiro para um pedaço de memória que, em seguida, fazer algum trabalho com.
>> Aqui está o grande problema com alocada dinamicamente a memória, porém,
e é por isso que é realmente importante desenvolver alguns bons hábitos
quando você está trabalhando com ele.
Ao contrário declarada estaticamente memória, a memória
não é automaticamente devolvida ao sistema quando sua função é feito.
Então, se temos principal, e principal chama uma função
f, quando f acabamentos seja o que está fazendo e devolve o controlo do programa
de volta à principal, toda a memória que f usado é dado de volta.
Ele pode ser usado novamente por algum outro programa,
ou alguma outra função que é chamado mais tarde na principal.
Ele pode usar a mesma memória de novo.
>> Se você dinamicamente alocar memória embora
você tem que dizer explicitamente o sistema que você está feito com ele.
Ele vai agarrar-lo para você, o que poderia levar a um problema de vocês se esgotando
de memória.
E, na verdade, por vezes, referem-se para isto como uma perda de memória.
E às vezes esses vazamentos de memória pode realmente ser realmente devastador
para o desempenho do sistema.
>> Se você é um usuário freqüente internet você pode usar determinados navegadores da web,
e eu não vou citar nomes aqui, mas existem alguns navegadores da web lá fora
que são notórias para realmente ter vazamentos de memória que não são fixos.
E se você deixa o seu navegador aberto para um período muito longo de tempo, dias
e em dias, ou semanas, você às vezes pode notar que seu sistema
é correndo muito, muito lentamente.
E a razão para isso é que o navegador alocou memória,
mas depois não contou o sistema que é feito com ele.
E assim que deixa menos memória disponível para todos os seus outros programas
ter que compartilhar, porque você é leaking-- que o navegador web
programa está vazando memória.
Como é que vamos dar de memória de volta quando estamos a fazer com ele?
Bem, felizmente, é uma maneira muito fácil de fazê-lo.
Nós apenas livrá-lo.
Há uma função chamada livre, que aceita um apontador para a memória,
e nós somos bons de ir.
>> Então, vamos dizer que estamos no meio do nosso programa,
queremos malloc 50 caracteres.
Queremos malloc uma matriz que pode capaz de reter 50 caracteres.
E quando temos um ponteiro de volta ao que, o nome do ponteiro é a palavra.
Fazemos o que nós somos vai fazer com palavra,
e, em seguida, quando estamos feito que apenas livrá-lo.
E agora temos devolvido os 50 bytes de memória de volta para o sistema.
Alguma outra função pode usá-los.
Nós não temos que se preocupar com um sofrimento vazamento de memória porque temos libertado palavra.
Nós demos a memória de volta, por isso, terminar de trabalhar com ele.
Portanto, há três regras de ouro que devem
ser mantido em mente sempre que você está alocar dinamicamente a memória
com malloc.
Cada bloco de memória que malloc você deve ser liberado
antes de seu programa termina a execução.
Agora, novamente, no aparelho ou no IDE esse tipo de acontece para você de qualquer maneira
você-- quando isso vai acontecer de qualquer maneira quando o programa é encerrado,
toda a memória será liberado.
Mas é geralmente boa codificação prática para sempre, quando você estiver pronto,
libertar o que você mallocd.
>> Dito isto, únicas coisas que você tem mallocd deveriam ser libertados.
Se você declarar um estaticamente inteiro, int x-e-vírgula,
que vive na pilha, você não, então queremos libertar x.
Então únicas coisas que você mallocd deveriam ser libertados.
>> E, por último, não fazer algo livre duas vezes.
Isso pode levar a outra situação estranha.
Então, tudo que você tem mallocd tem de ser libertado.
Únicas coisas que você malloc deveriam ser libertados.
E não fazer algo livre duas vezes.
>> Então, vamos passar por um exemplo aqui do que alguns alocada dinamicamente
memória pode parecer misto com alguma memória estática.
O que pode acontecer aqui?
Veja se você pode seguir ao longo e adivinhar o que está
vai acontecer como nós vamos através de todas estas linhas de código.
>> Assim, dizemos int m.
o que acontece aqui?
Bem, isso é bastante simples.
Eu criar uma variável inteira chamada m.
Eu colori-lo verde, porque essa é a cor
que eu uso quando estou falando cerca de variáveis ​​inteiras.
É uma caixa.
É chamado m, e você pode armazenar números inteiros dentro dele.
>> E se eu, em seguida, dizer int estrela um?
Bem, isso é bastante semelhante.
Estou criando uma caixa chamada a.
Ele é capaz de exploração int estrelas, ponteiros para inteiros.
Então, eu estou colorindo-verde-ish também.
>> Eu sei que tem algo a ver com um número inteiro,
mas ela própria não é um número inteiro.
Mas é praticamente a mesma idéia.
Eu criei uma caixa.
Ambos direita agora vivem na pilha.
Eu dei-lhes ambos os nomes.
>> int estrela b equivale ao tamanho de malloc de int.
Este pode ser um pouco complicado.
Leva um segundo e pensar sobre o que você seria de esperar que aconteça neste diagrama.
int estrela b equivale ao tamanho de malloc de int.
>> Bem, isso não basta criar uma caixa.
Isso realmente cria duas caixas.
E ela se liga, ele também estabelece um ponto em uma relação.
Temos atribuído a uma quadra de memória na pilha.
Observe que a caixa superior direito lá não tem um nome.
>> Nós mallocd-lo.
Ela existe na pilha.
Mas b tem um nome.
É uma variável ponteiro chamado b.
Que vive na pilha.
>> Portanto, é um pedaço de memória que aponta para outro.
b contém o endereço do bloco de memória.
Ele não tem um nome de outra forma.
Mas ele aponta para isso.
Assim, quando dizemos int estrela b é igual a malloc tamanho do int, que ali mesmo,
que a flecha que apareceu na lado direito lá, aquela coisa toda,
Eu vou ter que aparecer novamente, é o que acontece.
Tudo isto acontece em que uma única linha de código.
Agora nós vamos chegar pouco mais simples novamente.
um é igual e comercial m.
Você se lembra o que um é igual e comercial m é?
Bem, isso é um recebe o endereço de m.
Ou colocar mais esquematicamente, alguns pontos para m.
>> b é igual a um.
OK então aqui está um outro.
Um igual ao b.
O que vai acontecer o diagrama desta vez?
>> Bem recordar que o obras operador de atribuição
atribuindo o valor no direito de o valor do lado esquerdo.
Então, em vez de um apontador para m, uma empresa aponta para o mesmo lugar que b pontos.
um não aponta para B, A pontos onde b pontos.
>> Se um aguçado para b que faria ter sido um igual e comercial b.
Mas, em vez de um é igual a b apenas significa que a e b são agora
apontando para o mesmo endereço, porque dentro de b é apenas um endereço.
E agora dentro de um é o mesmo endereço.
m é igual a 10, provavelmente o coisa mais simples
nós fizemos em um pouco.
Coloque a 10 na caixa.
Estrela b é igual a m plus 2, recorde de nossa ponteiros vídeo que estrela b significa.
Nós estamos indo para dereference b e put algum valor em que a localização de memória.
Neste caso 12.
>> Então, quando nós dereference um ponto de lembrar que acabamos de viajar para baixo a seta.
Ou dito de outra forma, ir para esse endereço de memória
e manipulá-lo de alguma forma.
Nós colocamos algum valor lá.
Neste caso estrela b é igual a m mais 2 é apenas
ir para a variável apontada por b, ir para a memória apontada por b,
e colocar mais 2 m de lá, 12.
>> Agora eu libertar b.
O que acontece quando eu liberar b?
Lembre-se que eu disse meios livres.
O que estou dizendo quando eu liberar b?
>> Estou cansado de trabalhar com ele, certo?
Eu essencialmente desistir da memória.
Dou-lhe de volta para o sistema.
Eu não preciso mais disso é o que eu estou dizendo a eles, OK?
>> Agora, se eu digo uma estrela é igual a 11 você provavelmente pode
já dizer que algo ruim que vai acontecer aqui, certo?
E, de fato, se eu tentei que eu provavelmente sofreria uma falha de segmentação.
Porque agora, embora anteriormente que pedaço de memória
era algo que eu tinha acesso, neste ponto
Agora eu estou acessando memória que não é legal para mim para acessar.
>> E como nós, provavelmente, lembro, quando nós acessar a memória
que não é suposto ao toque, essa é a causa mais comum
de uma segmentação falha. E assim meu programa
deixaria de funcionar se eu tentasse fazer isso.
Então, novamente, é uma boa idéia para obter um bom práticas e bons hábitos enraizados
quando se trabalha com malloc e livre, de modo que você não sofre de segmentação
falhas, e que você usa seu alocada dinamicamente
memória de forma responsável.
>> Eu sou Doug Lloyd este é CS50.