O que é uma boa explicação para os ponteiros? [fechadas]


72

Nos seus próprios estudos (por conta própria ou para uma aula), você teve um momento "ah ha" quando finalmente entendeu realmente os indicadores? Você tem uma explicação usada para programadores iniciantes que parece particularmente eficaz?

Por exemplo, quando os iniciantes encontram ponteiros em C, eles podem adicionar &s e *s até compilar (como eu mesmo fiz uma vez). Talvez tenha sido uma imagem ou um exemplo muito bem motivado que fez os ponteiros "clicarem" para você ou seu aluno. O que foi e o que você tentou antes que parecia não funcionar? Houve algum pré-requisito de tópicos (por exemplo, estruturas ou matrizes)?

Em outras palavras, o que era necessário entender o significado de &s e *, quando você poderia usá-los com confiança? Aprender a sintaxe e a terminologia ou os casos de uso não é suficiente; em algum momento, a ideia precisa ser internalizada.


Atualização: eu realmente gosto das respostas até agora; por favor, mantenha-os chegando. Existem muitas perspectivas excelentes aqui, mas acho que muitas são boas explicações / slogans para nós mesmos depois de internalizarmos o conceito. Estou procurando os contextos e circunstâncias detalhados quando isso ocorreu a você.

Por exemplo:

Eu só entendi um pouco os ponteiros sintaticamente em C. Ouvi dois de meus amigos explicando os ponteiros para outro amigo, que perguntou por que um structpassador foi passado com um ponteiro. O primeiro amigo falou sobre como precisava ser referenciado e modificado, mas foi apenas um breve comentário do outro amigo em que me ocorreu: "Também é mais eficiente". Passar 4 bytes em vez de 16 bytes foi a mudança conceitual final que eu precisava.


16
Método 'Shotgun': jogue * s em qualquer lugar até que funcione.
Michael K

15
@ Michael: Sim, boa sorte com isso.
Robert Harvey

8
Esta questão surge logo depois no início de cada semestre no SO. A versão mais recente está aqui: stackoverflow.com/questions/4118647/…
Tim Post

10
O que é uma boa explicação para os ponteiros? Brian Kernhigan e Dennis Ritchie odeiam engenheiros de software.
quer

3
Ele "clicou" para mim depois de ter passado algum tempo codificando o código da máquina no depurador. Sim, eu estava familiarizado com o básico da arquitetura de computadores - aprendi montagem no Commodore 64, e o x86 ASM foi bastante direto depois disso. Então, eu já conhecia o conceito de "endereço", mas não entendi como ele mapeava as construções sintáticas de C.
Zvrba

Respostas:


25

Diagrama de memória como grade

Normalmente, o que faço é representar a memória como uma "grade", para que eu possa criar endereços, destacar diferentes espaços de memória e escrever nos valores das células (ou ainda mais, suas representações binárias) e vincular os ponteiros na memória aos valores que eles apontar para. (E depois ainda mencione que é uma simplificação).

Geralmente é um momento "ohhhh" para a maioria dos meus alunos.

Malabarismo com símbolos

Então, quando eles param de esquecer como usar & e *, é muito simples: apresente da mesma maneira que eles fazem cálculos de matemática ou física. Se você dividir uma distância em km por uma hora em hora, obtém uma velocidade em km / h. O que está dentro precisa estar fora. Simples.

printf para o Rescue

Fazer apenas alguns exemplos básicos que representam visualmente o que você explicou com eles os confortará no que eles pensam que entenderam, ou dará a eles a oportunidade de dizer "ah, eu não entendo esse".

Seja extenso

Cubra ponteiros para tipos simples e verifique se eles entendem a diferença entre endereçamento e tamanho de um tipo de dados, estruturas, matrizes e vários níveis.

Em seguida, inicie a aritmética do ponteiro.


Adendo: Recursão

Eu normalmente explico a recursão da mesma forma, usando uma representação visual. Peça que imprimam o alfabeto usando uma função pré-criada que escreve um único caractere e, em seguida, peça para que imprimam em ordem inversa, alterando apenas duas linhas.

Normalmente, há um "o que o ...?" momento, e quando você adiciona apenas outro parâmetro ao seu printf para imprimir valores numéricos e recuar as etapas, ele se torna um suspiro de alívio.


Alternativas: o modelo Play-Doh e os copos de água

Na verdade, tive alguns colegas de trabalho em uma universidade que mostraram aos alunos um vídeo explicando ponteiros e acessos à memória usando a pasta play-doh. Foi incrivelmente inteligente e bem-feito, embora eu nunca tenha realmente usado essa técnica, exceto por alunos muito jovens interessados ​​em entender a programação (mas geralmente aqueles que eu não os levaria a uma linguagem usando ponteiros muito cedo). Basicamente, usando pequenas bolas de brincadeira que você pode anexar a outras bolas maiores de brincadeira representando espaços de memória, e que você pode combinar para vinculá-las (como em uma estrutura de dados vinculada) ou mesclar (como em um contíguo espaço de memória). O uso de cores diferentes para os espaços de memória apontados e os ponteiros também ajudam. Mas ainda acho que a memória como grade funciona melhor, como você pode mostrar claramente que a indicação é realmente uma questão de "endereçar", como em um "mapa / grade". Enquanto o modo Play-doh ainda os confunde, pensando que as coisas realmente "se tocam" na memória.

A coisa Water Cup também foi usada diretamente por uma colega, mas não sei se ela a sugeriu. Foi uma abordagem interessante, mas notei que muitos alunos ficaram intrigados com a explicação. Algo parecido com a técnica da xícara de café da DevSolo . Mas acho que é realmente enganador, pois você faz os alunos confundirem contêineres, estruturas de dados, ponteiros e matrizes. Pode ser uma abordagem interessante para explicar matrizes no início, presumo, mas não me ateria a ela por muito tempo.


Uau, obrigado pela recompensa. Fico feliz que a resposta foi apreciada.
haylem

Desenhe: isso soa como um bom ensino!
Spooks

80

Alguém muito mais sábio do que eu disse uma vez:

A freira Wu Jincang perguntou ao sexto patriarca Huineng: "Estudei o sutra do Mahaparinirvana por muitos anos, mas há muitas áreas que ainda não entendo. Por favor, me esclareça."

O patriarca respondeu: "Eu sou analfabeto. Por favor, leia os personagens para mim e talvez eu possa explicar o significado".

Disse a freira: "Você nem consegue reconhecer os personagens. Como você consegue entender o significado?"

"A verdade não tem nada a ver com palavras. A verdade pode ser comparada à lua brilhante no céu. As palavras, neste caso, podem ser comparadas a um dedo. O dedo pode apontar para a localização da lua. No entanto, o dedo não é o Lua. Para olhar a lua, é necessário olhar além do dedo, certo? "


13
+1 para desreferenciar a lua. +1 para o koan, se eu pudesse.
Tim Post

14
Qual é o som da votação com um dedo?
Adam Crossland

3
@ Adam, que depende se você está usando um mouse ou um trackpad.
Daniel Joseph

7
@Frank Foi uma ótima citação. Ainda acho que não vai ajudar a entender a idéia. Especialmente para alguém novo para ponteiros.
Gulshan #

11
Esta é uma história bonita ... mas suspeito que as pessoas votem positivamente por causa disso, e não porque explica bem os indicadores.
21810 Kyralessa

46

Eu achei que os diagramas eram muito úteis. Exemplo:

diagrama de ponteiro


Esse tipo de diagrama me ajudou a ver que os ponteiros eram sua própria variável, mas continham um valor que era a localização de outro objeto, ou seja, matriz ou string. Além disso, quando feito a lápis, eu poderia usá-lo para rastrear meu programa em papel ou em um quadro-negro / quadro branco.


4
O valor dentro de "ponteiro" deve ser 4 ou os índices da matriz (ou endereços de memória) devem começar a partir de 0. Caso contrário, como um ponteiro que mantém o valor 3 aponta para o local 4?
MAK

++ É exatamente assim que eu iria explicar. Comecei em Fortran (para melhor ou para pior!). No Fortran, na época, usamos matrizes paralelas em vez de matrizes de estruturas (não existem coisas novas ). Se uma matriz continha um índice de "outra linha" nas matrizes, chamamos de "ponteiro", e isso era empolgante. Criamos listas, árvores, etc.
precisa saber é o seguinte

2
Acho os ponteiros melhor explicados usando imagens indicando o que está armazenado onde e setas para indicar onde os ponteiros apontam.
gablin

32

Quando eu "aprendi" sobre ponteiros pela primeira vez, fiquei meio empolgado. Minha universidade tomou a decisão muito tempo antes de eu me matricular para centralizar o currículo em Java; portanto, quando meu professor de Estruturas de Dados deu uma palestra em C e nos pediu para implementar uma lista XOR com indicadores, senti que estava entrando em algo muito acima da minha cabeça.

Eu entendi a definição:

Um ponteiro é uma variável que contém o endereço de uma variável

Mas ainda não entendi grande parte do conceito. Olhando para trás, acho que estava centrado em três coisas:

  1. O que exatamente é um local de memória? (Na época não participei de uma aula de Organização de Computadores)

  2. A sintaxe incômoda (Então, hum ... por que exatamente ela é definida como "int * ip", mas depois me refiro à variável como "ip"?)

  3. Como exatamente é benéfico armazenar o endereço de uma variável em vez de apenas usá-la?

Não foi até eu comprar o livro K&R e completar todos os problemas que eu realmente compreendi as dicas. Além do fato de eu ter concluído há muito tempo a aula de Organização do Computador (que acho que deveria ser necessária antes de aprender C), parte disso tinha a ver com o fato de perceber que os ponteiros podem ser usados ​​para funções, matrizes, estruturas ... fazer coisas úteis e não apenas como armazenamento para endereços de variáveis ​​comuns.

Mas o meu momento "aha" foi de longe o modo como a K&R explicou a sintaxe incômoda de definir um ponteiro simples. Tomei notas ao longo do livro (em que refizendo as observações feitas pelo livro em minhas próprias palavras, a fim de aprofundar minha compreensão), e este é o que diz respeito a isso:

Um ponteiro é uma variável que contém um endereço para uma variável. Um ponteiro é definido e desreferenciado (produzindo o valor armazenado no local da memória para o qual aponta) com o operador '*'; a expressão é mnemônica.

Ex.: 
   int a;      /* Variable 'a' is an integer */

   int *ip;   /* Variable ip is a pointer and dereferencing it gives an integer.
                 In other words, the expression *ip is an int, so ip is a pointer
                 to an int */

Eu sempre senti que não podia entender completamente os conceitos mais avançados de ponteiros até ter algo tão elementar enraizado na minha cabeça. Isso me incomodou incessantemente depois daquela tarefa (a qual não fiz muito bem, aliás;)) por que "* ip" não existia logo depois que eu (pensei que eu) defini "* ip". Dominar isso é essencial para conceitos mais avançados que envolvem ponteiros, como ponteiros de função e definições mais complicadas como esta:

char (*(x())[])()

Em suma, acho que o conceito de ponteiros requer:

  1. Um entendimento básico de como a memória é organizada em um computador (e o que é memória).

  2. Conhecimento de quão poderosos os ponteiros podem ser (uso no mundo real, não apenas outro conceito abstrato que eles aprendem para aprender).

  3. Decifrando os hieróglifos conhecidos coloquialmente como "uma definição de ponteiro"

Então, apesar de tudo, acho que deveria haver pelo menos três momentos "aha" ao aprender sobre ponteiros. Ainda sou estudante, então pensei que você apreciaria o ponto de vista de alguém que ainda está (relativamente) fresco aprendendo o conceito.


+1 nos 3 "Ah ha!" monentos. Os ponteiros de groking vêm em camadas. I "entendido" pontos por um longo tempo antes de eu percebi que apenas cerca de metade entendido ponteiros para ponteiros :)
Binary Worrier

Eu acho que você está totalmente correto, pois uma parte muito grande de 'não entender ponteiros' está, na verdade, tropeçando na estranha sintaxe C. [Pensa: Eu me pergunto o quão difícil seria para Grokar com este tipo de sintaxe: PointerTo<int> a]
Benjol

De acordo, @Benjol. Estou surpreso que a sintaxe int* ipnão seja mais comum. Finalmente comecei a entender os ponteiros depois que vi um código formatado dessa maneira. Então eu poderia lê-lo como "ip é do tipo int pointer".
Jacob

19

O ponteiro é um pouco como os atalhos de aplicativos na área de trabalho. Exclua o atalho e o destino ainda existe. Inicie o atalho e o destino será iniciado.

Eu sempre explico o funcionamento disso criando um arquivo txt na minha área de trabalho e dois atalhos para o arquivo. Após copiar e excluir os atalhos, você pode ver as pessoas entenderem a ideia por trás de 'referências'.

Quando o grupo entender o básico por trás dos atalhos, você poderá começar a explicar os ponteiros da maneira que desejar. Eles provavelmente entenderão isso facilmente.


Essa não é uma analogia ruim. Apenas alguns pontos a acrescentar para quem considera literalmente um "link físico" sempre apontam para seu destino, mesmo que ele mude de diretório, um ponteiro apontará para a memória original, mesmo que o objeto tenha sido realocado. Um "link físico" informará quando o destino não existir mais, um ponteiro pendente deve ser definido como NULL.
snmcdonald

Um link físico é como um ponteiro inteligente contado como referência
jk.

11
+1. Uma das melhores analogias práticas para explicar os ponteiros. Estou certo de que os alunos entenderiam a idéia imediatamente, pois essa funcionalidade é a mais usada por todos.
Karthik Sreenivasan

13

8 a 10 anos atrás, eu ensinei um curso de introdução "C" em uma faculdade comunitária. Este sempre foi um tópico divertido de explorar. O que parecia funcionar melhor, e isso foi depois de discutir algumas vezes com um colega de trabalho: usar uma xícara de café e sua mão.

Eu usei a analogia de uma xícara de café (ou uma linha delas para matrizes) como uma variável (pode conter alguma coisa). Eu então usei minha mão, que também poderia segurar algo ou, estendendo meu dedo indicador para "apontar para" uma xícara de café.

Uma mão fechada era nula, um dedo apontando para minha cabeça (como uma arma simulada) era um ponteiro pendurado.

Depois, com algumas demonstrações e viagens pelo depurador, ele clicou com a maioria.


3
Você já me confundiu.
precisa saber é o seguinte

11
@ Kirk, como assim? deixe-me ver se consigo esclarecer.
precisa saber é o seguinte

4
++ Não há nada como ensinar para fazer você pensar sobre essas coisas.
Mike Dunlavey

Um dos meus professores na universidade fez uma coisa semelhante, usando estudantes (um dos quais era "Niel", para risadas adicionais), em vez da xícara de café. Apontando com a mão para a platéia estava um ponteiro pendurado, porque poderia estar apontando para qualquer coisa.
Kaz Dragon

2
Um ponteiro pendurado é mais como apontar para Neil, em seguida, fazê-lo sair da cadeira sem mudar para onde você está apontando ... depois, tentar seguir esse ponteiro e interpretar o que você encontra lá como Neil, independentemente de quem acabou lá.
Jon Purdy

10

Fico realmente preocupado quando ouço a pergunta "como você conseguiu entender os ponteiros". Eu sempre achei o conceito incrivelmente simples e uma evolução lógica das linguagens, fornecendo grande poder aos programadores.

O que me preocupa é que nunca achei difícil entender o conceito de ponteiros. Então, quando você aqui "quando finalmente conseguiu" repetidamente, começa a pensar:

Eu realmente entendo? Talvez eu nunca tenha feito?

Talvez a razão pela qual o conceito pareça complicado, seja porque continuamos dizendo a todos que ainda os encontraram que os indicadores são tão difíceis, e aqui estão centenas de maneiras pelas quais você pode aprender?

Apenas lançando essa idéia, é claro que pessoalmente adoro um bom diagrama e Steve Gibson sempre faz um trabalho fantástico de explicar qualquer coisa !


Interessante ... qual idioma você usava na época? Eu acho que a sintaxe C atrai muitas pessoas. Se você conhecesse a assembléia primeiro, poderia ver que essa é uma razão. [BTW, eu quero votar isso, mas eu alcancei meu boné para hoje.]
Macneil

Curiosamente, eu não tinha conhecimento de indicadores "perigosos" por um longo tempo, trabalhando em Python (e Java na Universidade). Então peguei um módulo de "métodos orientados a objetos" que usava C ++ como a linguagem de escolha e mergulhou direto lá.
Marcus Whybrow

Também acho que entender como um programa é representado na memória pode definitivamente ajudar, mas acho que prefiro dizer que entender por que os ponteiros foram uma adição útil a uma linguagem é o ângulo mais eficaz, pois você está passando pelo mesmo processo como os designers originais.
Marcus Whybrow

+1 Não faço ideia de por que as pessoas pensam que os indicadores são difíceis ou misteriosos.
ggambett

Sim, os ponteiros sempre foram tão obviamente simples e úteis que não consigo imaginar pensando que haja algo "difícil" neles. Eu odeio quando um professor de qualquer curso diz "agora, isso é um pouco complicado" porque é muito subversivo. Apenas ensine as malditas coisas e deixe que os alunos decidam por si mesmos se acham que é complicado.
Jon Purdy

7

Eu nunca tive muito problema com ponteiros em C, mas isso pode ser porque eu tive que aprender primeiro o assembler. Na verdade, foi um alívio não ter mais que administrar meus endereços. Talvez a resposta (supondo que isso seja algo que você esteja ensinando) seja oferecer aos alunos uma linguagem assembly emulada para trabalhar. Eles vão descobrir isso no processo de escrever qualquer coisa mais sofisticada do que "Olá, mundo".


+1 para adaptar uma abstração mais primitiva, em vez de tentar usar uma analogia.
Tipo anônimo

Na minha escola, uma unidade de Estudos de Computação era dedicada ao estudo de um computador de caixa de fósforos , que pode ser ensinado a partir do quadro-negro sem nunca tocar ou envolver um computador real.
Rwong

@Larry Coleman, Assembly !!!!!!!!!!! Quero experimentá-lo antes de C. Por favor, diga-me por onde começar a aprender. Ebooks grátis, PDF grátis? IDE? Por favor!!!!!!!!!!!!!!!!!!!
Spacez Ly Wang 17/10/12

7

Um ponteiro é uma variável cujo valor é o endereço de memória de outra variável.


Elegante, por que torná-lo mais complicado.
Bjarke Freund-Hansen

Se os ponteiros não parecerem imediatamente intuitivos e úteis, eles foram explicados incorretamente.
quer

6

Como eu realmente aprendi sobre ponteiros? Ao escrever um compilador simples, o primeiro ano de faculdade.

Como explicar os ponteiros em termos leigos? Gosto da analogia (datada?) De um catálogo de biblioteca armazenado em cartões de índice. Cada cartão ("ponteiro") contém informações sobre a localização de algum livro ("dados"), mas na verdade não contém o próprio livro. Se você modificar o cartão ("aritmética do ponteiro"), tudo o que ele faz é alterar para qual livro ele aponta e não tem impacto no próprio livro - apenas tome cuidado para não estragar o endereço ou você pode apontar para um livro inexistente ou mesmo a biblioteca errada. No entanto, se você seguir o "endereço" no cartão e for para a parte apropriada da biblioteca ("desreferenciar o ponteiro"), poderá ver / modificar o próprio livro.


+1 para a memória do meu curso CS onde eu tinha exatamente essa explicação
Gary Rowe

Isso é bom de certa forma, mas um tanto enganador, pois as cartas não dizem onde está o livro. Você ainda precisa executar um algoritmo de pesquisa orientado a tênis. Talvez isso modele melhor um banco de dados - referindo-se a um objeto armazenado por uma chave (número de chamada).
darenw

+1 A analogia mantém o mesmo conceito que o explicado por Barfieldmv, mas com uma abordagem mais real.
Karthik Sreenivasan

5

Suponho que alguém que vai aprender ponteiros sabe quais são as variáveis ​​normais e como elas funcionam em C. Agora, vamos tentar definir ponteiros com alguns de seus atributos -

  • Eles também são variáveis, mas de natureza diferente. Suponha que haja duas camadas no espaço variável. As variáveis ​​normais de diferentes tipos residem na camada superior e ponteiros na camada inferior. Como esta figura-

    texto alternativo

  • Como o nome 'Ponteiro' sugere, os ponteiros podem apontar para alguma coisa. Como nosso dedo pode apontar para algum objeto. Quais são as coisas para as quais eles apontam? Essas são as variáveis ​​normais. Em resumo, "Ponteiros apontam para variáveis ​​normais".

  • Como variáveis ​​normais, os ponteiros também são do mesmo número de tipos, como int, char ou float. E um ponteiro de um tipo específico pode apontar para apenas o mesmo tipo de variáveis.
  • Um ponteiro pode apontar para uma variável e, posteriormente, o mesmo ponteiro pode apontar para outra variável. Apenas o tipo deve ser o mesmo. Portanto, a associação de um ponteiro com alguma variável não é permanente e pode ser alterada.
  • Então, como um ponteiro é declarado? Quase como variáveis ​​normais. Você deve preceder o nome com um asterisco ( *). Gostar-

    int *pointer;
    
  • Então, como um ponteiro está associado a uma variável? Usando o &operador antes da variável como esta declaração

    pointer = &variable;
    
  • Como um ponteiro é usado apontando para uma variável? Isso também é feito precedendo o nome com um asterisco ( *). Em seguida, ele pode ser usado no lugar da variável que está apontando agora -

    *pointer = var1 + var2;
    

    ao invés de

    variable = var1 + var2;
    
  • Agora, brinque com ponteiros com algum código. Acostume-se a essas características dos ponteiros agora. Até este ponto, estamos falando sobre o que os ponteiros fazem. Quando estiver de acordo, comece a estudar como os ponteiros estão apontando para alguma variável e como eles reagem se operações aritméticas normais forem aplicadas a elas. Em seguida, vá para a relação entre ponteiros e matrizes e ponteiros para ponteiros.

Isso é tudo o que vou sugerir sobre o aprendizado de indicadores.


Eu queria seguir o processo "primeiro o que faz e depois como". Abstração!
Gulshan #

5

Editado em suporte ao requisito revisado da pergunta

Meu caminho para o entendimento "pós-ponteiro" (se bem me lembro) foi assim. Eu tive uma experiência simples de programação de montagem de quando ainda estava mexendo com um BBC Micro, então tive o conceito de memória como um monte de caixas (veja abaixo). Isso foi reforçado pelo uso de matrizes. No entanto, eu estava entrando no mundo do C e tive que lidar com strings, o que significava ponteiros. No BASIC, isso foi trivial, no assembler eu nunca tive que trabalhar com eles, e agora no clássico C são todos indicadores e outras coisas. Ah, mas posso voltar às matrizes com strings (terminação nula) como esta:

char s[] = "Hello, world!";
printf("%s",s);

Tudo bem, isso é apenas uma matriz de caracteres (8 bits por caractere no meu pequeno mundo) com um caractere zero no final para mostrar onde termina. O printf apenas pega esse array e passa por cima dele, imprimindo-o. Mas e se eu quiser passar essa string para uma função?

void print_str(char* p) {
  printf("%s",p);
}

É o que o manual diz, mas o que é isso *? Hmm, char * significa "ponteiro para um char". OK ... me perdi. Então me ocorreu que o caractere * faz p equivalente a s [0]. OK, eu posso usar isso, mas ainda não entendi o que são indicadores. Quero dizer, como faço para definir alguns dados com uma dessas coisas? Off para o manual novamente ...

char* p = "Hello World!";

Enquanto escrevo o texto acima, estou dizendo a mim mesmo "declare um ponteiro para um caractere e defina-o como esse conjunto de caracteres". De alguma forma, esse ponteiro elimina a necessidade de uma matriz. Acho que é o compilador fazendo algumas coisas para mim, para variar. Então, como posso alterar a matriz com esse ponteiro? Eu sei que eu poderia usar a versão do array

 s[2] = 'L'; 

mas qual é o equivalente em "falar com ponteiro"? Fora para esse manual novamente ...

*(p+2) = 'L';

Suponho que * significa simplesmente "o conteúdo do endereço de memória" e (p+2)é s[2]. O que significava que o ponteiro p era ... apenas ... um ... endereço ... bong!

Que existe o som da iluminação. De repente, girei ponteiros (foi há muito tempo, nós, veteranos, não "grocávamos" até mais tarde). Foi apenas indireto.


Original:

OK, meu valor 2c:

Imagine que a memória é um monte de caixas. Cada caixa tem um número ao lado (o endereço). Cada caixa contém um número (o conteúdo). Você pode trabalhar com essas caixas de duas maneiras: variáveis ​​(eu quero o conteúdo da caixa N), ponteiros (eu quero o conteúdo da caixa, o que estiver na caixa N ). Ponteiros são simplesmente indiretos.

E para a grande resposta que cobre tudo o que você precisará saber - leia isso .


++ É mais ou menos assim que eu ensinei o assunto.
precisa saber é o seguinte

Artigo editado para dar suporte aos requisitos de OP.
Gary Rowe

Qual manual você estava usando que adicionou caracteres NUL extras no final de suas strings?
Rob Gilliam

@raimesh Um muito antigo (por volta de 1991). Não me lembro qual.
Gary Rowe

1991? Isso não é antigo para um manual em linguagem C - a 1ª edição da K&R foi publicada em 1978! Apenas fiquei intrigado com a existência de um manual sugerindo que você precisava colocar \ 0 no final de suas constantes de string. (Na verdade, olhando para ele de novo, você quis dizer para colocar \ n?)
Rob Gilliam

4

Pegue alguns pequenos blocos de madeira.

adicione ganchos de metal em uma extremidade e olhos de metal na outra.

agora você pode fazer uma lista vinculada de itens com os quais pode brincar.

Tente explicar com este suporte físico. Eu sempre desejei ter isso ao ensinar sugestões para os alunos do primeiro ano.

O gancho de metal é o ponteiro, o bloco de madeira que a coisa apontou.

Eu confio em alguém para não conseguir depois de brincar com os blocos.


4

Eu facilitei minha vida quando apenas removi todo o cotão e comecei a tratar o ponteiro como qualquer outra variável, e não como uma entidade mágica (há muito tempo na série 11) .. apenas saiba três coisas:

  1. Ponteiro é uma variável que armazena o endereço de outra variável (ou qualquer endereço).
  2. * é usado para obter o valor no local da memória armazenado na variável do ponteiro.
  3. O operador & fornece o endereço de um local de memória.

O resto é açúcar sintático e bom senso. Basta escrever alguns programas C simples (como implementar uma biblioteca de listas vinculadas) usando ponteiros para entender o problema.


2
  1. O ponteiro pode ser pensado como uma generalização de um índice em uma matriz.
    • Considere que uma grande matriz pode ser dividida em várias matrizes menores, sem sobreposição e de tamanho variável. Agora, essas matrizes menores são o que geralmente pensamos como matriz. Quanto maior, então, todo o espaço da memória do computador. O processo de cortar matrizes menores é chamado de alocação de memória.
  2. Um conjunto de estruturas vinculadas por alguns ponteiros pode ser pensado como um gráfico direcionado .
    • Cada vértice é uma variável que pode conter algum valor.
    • Algumas variáveis ​​são ponteiros e cada ponteiro pode ter exatamente uma borda de saída em outra coisa.
    • Variáveis ​​que não são ponteiros não terão nenhuma borda de saída. Eles poderiam ter qualquer número de margem de entrada.

2

Não me lembro bem das circunstâncias em torno dos meus ponteiros, aha-moment, mas reajustei retroativamente a memória em torno da minha compreensão de uma matriz de estilo c. (ou seja, arr[3]é o mesmo que *(arr+3))

Por alguma razão, acho imensamente útil visualizar ponteiros como matrizes sempre que me deparei com uma situação de ponteiro.


2

Basicamente, Gary Rowe apresentou o modelo certo. Memória como um conjunto de caixas com endereços (números) nelas. Cada caixa armazena um valor (número).

A idéia de um ponteiro é interpretar o valor em uma caixa como o endereço de outra caixa. Este valor é usado para se referir a uma caixa específica, razão pela qual é chamada de referência . Portanto, a desreferenciação é o processo de abertura da caixa a que se refere.

se vfor uma variável (caixa), a instrução

  • vsignifica valor de v, ou seja, me dê o que está na caixa
  • *vsignifica desreferenciar o valor de v, ou seja, me dê o que está na caixa referida pelo valor dev
  • &vsignifica referência v, ou seja, me dê o endereço na caixa

Eu acho que não tem como objetivo introduzir ponteiros como algo completamente diferente. Era um conceito difícil de entender para mim quando eu era criança. Sempre pareceu uma magia negra que eu nunca entendi, que precisava de muitos personagens especiais. A primeira vez que entendi foi quando escrevi um pequeno jogo usando o duplo indireção em uma linguagem que não possui aritmética de ponteiro. Isso me iluminou.

Ponteiros são uma questão de interpretação. Eu acho que explicar isso facilita muito as coisas. E a aritmética de ponteiros são operações extremamente simples e intuitivas, se mostrado um exemplo simples com uma memória de 10 variáveis.


2

A explicação que eu realmente grocked foi:

Considere uma grade da cidade com diferentes casas construídas em terrenos. Na sua mão você segura um pedaço de papel. No papel que você escreveu:


Casa de David,

112 Tão e tão rua.


O pedaço de papel (variável do ponteiro) contém um endereço que aponta para a casa de David. Quando você quer dizer a um amigo para dar uma olhada na casa legal de David, é muito mais fácil usar o pedaço de papel como referência para a casa do que enviar o prédio de dois andares pelo correio.

Tal como acontece com os ponteiros reais, você pode ter alguns problemas quando segue o endereço no seu pedaço de papel. David poderia ter se mudado e, quando você chega lá, encontra um grande buraco no chão. Nesse caso, teria sido melhor apagar o endereço no papel quando David se mudou ou pelo menos alterá-lo para o novo. Você também pode achar que vai ao endereço e digita o que acha que é a sala de estar do seu amigo David, mas desta vez você acaba em uma piscina completa para desconhecidos. Outra pessoa usou o espaço no endereço que você tinha para algo completamente diferente.


2

Se você deseja explicar os ponteiros, deve explicar a memória primeiro. Eu costumo fazer isso usando papel milimetrado / papel quadriculado com linhas e colunas. Se o "aluno" entender a memória, poderá entender o que é um endereço. Se você tem endereço, você tem ponteiros.

Você pode brincar com essa abstração. Por exemplo, escreva o endereço (número) de um quadrado em outro quadrado. Agora desenhe uma seta do quadrado do ponteiro para o quadrado de destino. Agora substitua o ponteiro (por exemplo, aumente-o) e ajuste a seta. Escreva um endereço em outro quadrado e deixe o aluno desenhar a flecha ...

Próximo passo: dê um nome a certos quadrados (como o ponteiro). Agora você pode explicar a desreferenciação. É isso aí.


2
Lembra-me de um "computador" que eu usei antes que eu pudesse colocar minhas mãos em um que realmente usava elétrons - o cartão "CARDIAC" que eu acho que foi chamado. Literalmente, escrevendo números em caixas numeradas para obter números de outras caixas numeradas. Ele foi educacional e nunca tive problemas para entender ponteiros em microprocessadores reais.
darenw

2

Talvez seja só eu, mas trabalho bem com analogias. Então, digamos que você tenha um amigo (função / classe) "Foo", que queira ter outra pessoa (função / classe diferente), "Bar", entre em contato com você por algum motivo. "Foo" pode levá-lo a ver "Bar", mas isso não é conveniente, movendo todos esses seres (instâncias). No entanto, "Foo" pode enviar "Bar" ao seu número de telefone (ponteiro). Dessa forma, não importa onde você esteja, "Foo" sabe como entrar em contato com você sem precisar encontrá-lo.

E, digamos que "Bar" tenha um conhecido, "Baz", que também quer entrar em contato com você. Mas você é protetor do seu número de telefone e não quer que todos tenham, "Baz" pode ligar para "Bar" (telefone como ponteiro), que pode encaminhar a chamada para você (outro ponteiro). E assim por diante na cadeia de amigos de "Baz" e amigos de amigos.


2

Os ponteiros fazem muito mais sentido se você estudou a linguagem assembly e / ou a arquitetura do computador. Penso que se eu ministrasse uma aula em C, começaria com algumas semanas de arquitetura para explicar o modelo de memória e os tipos de instruções que o processador realmente executa.


Absolutamente. Quando você lida com registros e entende coisas como valores imediatos e endereçamento indireto, todo o conceito de ponteiros é intuitivo. Aprendi a montagem 6502 e a montagem em 68K antes de escrever minha primeira linha de C; assim, quando fui apresentado aos ponteiros, observei a montagem (intermediária) do compilador e estava exatamente como o esperado.
Radian

2

Meu "aha!" momento chegou neste tutorial:

Um tutorial sobre ponteiros e matrizes em C

Para ser exato, veio neste capítulo: Capítulo 3: Ponteiros e seqüências de caracteres

Para ser ainda mais preciso, veio com esta frase:

O parâmetro passado para puts () é um ponteiro, que é o valor de um ponteiro (já que todos os parâmetros em C são passados ​​por valor), e o valor de um ponteiro é o endereço para o qual aponta, ou, simplesmente, um endereço .

Quando li isso, as nuvens se abriram e os anjos tocaram trombetas.

Pois, veja bem, todos os tutoriais ou livros em C que eu li antes afirmaram que C poderia passar por valor ou por referência, uma mentira nefasta. A verdade é que C sempre passa por valor, mas às vezes o valor passado passa a ser um endereço. Dentro do método, é feita uma cópia desse endereço, assim como uma cópia de um int passado. Uma cópia não é feita do valor para o qual o ponteiro aponta. Assim, usando o ponteiro dentro do método, você pode acessar o valor original e alterá-lo.

Eu nunca me tornei um programador C, mas me tornei um programador .NET, e objetos e referências a objetos funcionam da mesma maneira; a referência ao objeto é passada por valor (e, portanto, copiada), mas o próprio objeto não é copiado. Eu trabalhei com muitos programadores que não entendem isso porque nunca aprenderam dicas.


1

O truque é explicar que a localização de uma coisa e a própria coisa não são as mesmas, assim como a imagem de um cano não é um cano . Quando você move uma coisa, sua localização muda. A localização permanece e outra coisa pode ser colocada lá.


1

Um ponteiro é uma nota adesiva que informa onde algo é útil. Ele contém a localização da coisa e informa o tamanho da coisa (em C, pelo menos). Portanto, um ponteiro duplo é como uma nota que diz "Há um pacote de seis na geladeira". Você precisa pegar o pacote de seis para descobrir se é Coca-Cola ou Budweiser.


1

Dado o código:

int v=42; // declarando e inicializando uma variável simples

int *p = &v; // criando um ponto p para a variável v

Pode-se dizer o seguinte sobre o código acima:

int * p // "int pointer p" ... é assim que você declara um ponteiro para a variável do tipo int

*p // "apontado por p" ... são os dados para os quais p aponta, é o mesmo que v.

&v // "endereço da variável v" ... isso representa o valor literal de p


1

http://cslibrary.stanford.edu/

Este site possui ótimos tutoriais para aprender ponteiros e gerenciamento de memória.

Eu sugiro que você percorra os fundamentos dos ponteiros, os ponteiros e a memória fornecidos no site. Você também pode examinar os problemas das listas vinculadas fornecidos no link para fortalecer ainda mais os conceitos do ponteiro.


1

A chave para explicar os indicadores é garantir que as pessoas para as quais você está explicando já tenham um entendimento do conceito de memória. Embora seria bom se eles realmente entendessem o nível baixo, acreditar que a memória existe como uma matriz massiva e entender que você pode acessar qualquer posição na matriz pela localização do índice é suficiente.

A próxima etapa, ter o conceito de passar o local do índice em vez de copiar toda a memória faz sentido para a maioria das pessoas. E isso é suficiente para permitir que a maioria das pessoas entenda por que os ponteiros são úteis.

a etapa final para entender os ponteiros é explicar como você pode passar como parâmetro um local de índice de memória para o método para armazenar o local de índice para onde todos os dados estão armazenados. Eu descobri que isso pode ser um passo longe demais para algumas pessoas.

Depois que alguém entende essas etapas básicas, é fácil entender que você pode encadear ponteiros indefinidamente, desde que você acompanhe quantas vezes precisa procurar endereços para encontrar o objeto de dados real.

Depois que alguém compreende os ponteiros, a próxima coisa que eles devem entender rapidamente é a diferença entre a memória heap e a pilha, e por que os ponteiros para empilhar memória são perigosos quando passados ​​para fora do método.


0

Lembro-me de um livro "quebra-cabeças C" ou similar, que li puramente por ser um dos poucos livros relacionados a programação / computador disponíveis na biblioteca, meu entendimento de C era rudimentar. Ele jogou uma expressão C em você e pediu para explodir, ficando cada vez mais complicado.


0

Quando eu estava na universidade, meu professor tinha alguns slides em powerpoint realmente legais que descreviam um ponto como uma variável separada por si só, com uma seta para um local de memória (representado como uma matriz) e, quando estávamos fazendo listas vinculadas, ele fazia isso passo a passo, mostrando quando a seta muda, quando o ponteiro é desreferenciado, etc ..., não havia como alguém não conseguir entendê-lo em alguns minutos. O conceito em si é realmente fácil, mas fazê-lo corretamente ou aplicá-lo em programas práticos exige mais prática.


0

Antes de fazer isso, explico que na programação "tudo usa memória" e alocação de variável (estática) na memória. Também explicarei o que é um endereço de memória e a relação entre espaço, endereço e variáveis ​​de memória.

Por fim, explico que existem tipos e variáveis ​​de dados inteiros, tipos de dados e variáveis ​​de string ... e assim por diante, até explicar que há um tipo de dados especial que armazena endereços de memória, que possui um valor vazio como 0 o "", chamado nulo .

E, finalmente, variáveis ​​alocadas dinamicamente através do uso de ponteiros.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.