PplWare Mobile

Vamos Programar? – Introdução à Programação #18

                                    
                                

Este artigo tem mais de um ano


Autor: Henrique Dias


  1. Steve says:

    Olá, esta rubrica é muito boa.
    Podias explicar porque por vezes é melhor utilizar apontadores? Mais concretamente em termos de ocupação de memória ram.

    • nibbleShifter says:

      Com apontadores estás a aceder à posição de memória onde a variável está armazenada, ou seja, estás a manipular directamente o armazenamento da variável.
      Quando utilizas uma função para manipular variáveis, estás apenas a manipular um cópia dessas variáveis, mantendo o valor das variáveis originais inalterado, ou seja não estás a manipular a vairável armazenada na posição original, mas sim um cópia, armazenada noutra posição de memória.
      A utilização de apontadores permite definir em que posição de memória queres alojar o valor x ou o valor y, dando-te total controlo na gestão da memória. Podes por exemplo utilizar a mesma posição para armazenar variáveis diferentes em pontos de execução do programa diferentes, isto possibilita a poupança de um byte, ou mais, no runtime do programa, uma vez que estás a utilizar sempre a mesma posição para armazenamento, em vez de utilizares várias posições.
      Em C e C++ a gestão de memória é muito importante porque pode ser totalmente controlada pelo programador, ao invés do Java e do C#, onde há garbage collectors que tratam da limpeza das variáveis não utilizadas, automacticamente.
      Uma utilização “responsável de apontadores” permite evitar erros durante o runtime, nomeadamente as falhas de segmentação.

      Os apontadores são bastante úteis na programação de baixo nível, por exemplo no kernel des sistemas operativos ou em sistemas embebidos bare metal ou não, onde a gestão da memória é feita. Não é por acaso que praticamente todos os sistemas operativos são programados em C ou C++ no seu kernel.

    • Bruno says:

      porque os apontadores sao dinamicos, nao necessitas de alocar logo todo o espaço da memoria

    • lmx says:

      Steve,

      “Podias explicar porque por vezes é melhor utilizar apontadores? Mais concretamente em termos de ocupação de memória ram.”

      A resposta é simples 😉
      O C só tem passagem de valores por cópia.

      Não sei se estudas-te assembler?irias perceber porquê 😉

      Ao passares valores como parametros ás funções, são automaticamente copiados para o stack da função…

      Se tiveres uma estructura gigante, não a vais passar como parametro para a função, porque nesse caso irias copiar toda a estructura para a função…isso era um horror, porque gastavas muita memoria, e além disso a tua função era lenta…e além disso, podia ocurrer o caso como em algumas archś de ficares sem memoria no stack 🙁

      Então o que fazer?mandas o pointer para essa estructura, a função copia-o(o pointer para dentro da função), e manipulas o struct(ou não), de dentro da função 😉

      Outro factor, acho que já foi referenciado acima…é que as variáveis só são visíveis no “scope” dessa função…ou seja dentro do stack da função!
      O assembler iria ajudar-te a perceber porquê 😉 e podes parar o compiler tollchain a seguir ao compilador e ver o código 😉

      Se dentro de uma função queres manipular uma variável que está fora…a única hipotse é passar o endereço de memória dessa variável para a função, dessa forma a função copia o endereço, e depois de dentro da função(no stack), manipulas a variável 😉

      cmps

    • Joao says:

      O exemplo “classico” na universidade era a utilização de ponteiros para criar uma lista telefónica. Se tivesses que definir um array estático no inicio do programa para, por exemplo, 1000 contactos, estarias a desperdiçar memória se o utilizador só fosse utilizar 200 contatctos. Se o utilizador ultrapassar os 1000 contactos o programa rebenta, pois já esgotou a memória disponivel. Assim, é melhor usar ponteiros e o programa vai alocando memoria para cada contato inserido, à medida das necessidades do utilizador. Os ponteiros são um pouco complicados, mas são uma arma poderosa. Além do facto de puderes utilizados para alocar memória há medida do necessário, podes usa-los para apontar para outras variáveis e utilizar esta vertente para a construção da lógica do teu programa

    • Olá Steve.

      Em primeiro lugar, obrigado. Em segundo, a maravilhosa comunidade de leitores já respondeu e MUITO bem à sua questão.

      Finalmente, Desejo um Bom Ano Novo a todos vós 🙂

  2. PsySc0rpi0n says:

    Boas…

    Um pormenor que é capaz de ajudar a complementar as explicações dadas.

    Para além do que já foi dito, é recomendável relembrar que as variáveis declaradas dentro de uma função (variáveis locais), “perdem-se” assim que a função termina, por isso é que no exemplo 3, no primeiro código, as variáveis que queremos manipular, não são alteradas.

    cUMPs
    Psy

  3. Jose Simoes says:

    Umas notas notas somente. Não altera nada a exposição, mas prepara as ideias para futuros desenvolvimentos.

    O uso de apontadores, apesar de muito poderoso, cria imensas oportunidades de erro, alguns erros de difícil diagnóstico. Nunca subestimem a capacidade de fazer confusão quando se usam apontadores, nomeadamente apontadores que apontam para apontadores ou para estruturas que contêm apontadores.

    Mesmo em C, desde o padrão 99, a alocação dinâmica de memória já não passa exclusivamente pelo uso de apontadores e os métodos alternativos devem ser usados para uma programação mais segura (e fácil). Isto não quer dizer que não se deva compreender os apontadores, mas que escrever código de fácil manutenção exige métodos alternativos sempre que possível e eficaz.

    O C é uma linguagem de origem antiga e por isso tem certas limitações subjacentes ao era boa ideia décadas atrás.

    Linguagens mais recentes como o C++, e algumas antigas mas não o C, permitem modificar variáveis passadas para funções sem o perigo extra de usar apontadores para essas variáveis. Na prática é como se se utilizar apontadores, mas não há o perigo de adicional que advém do uso de ponteiros.

    Só uma + notinha. Desde a primeira versão padrão ISO/ANSI de C que o NULL vele o mesmo que 0 (zero), embora isso não seja garantido em versões anteriores. Por isso a minha recomendação foi colocar sempre um 0 no local de NULL. No entanto a compreensão do significado de NULL é importante porque existe muito código que o usa, mas eu não recomendo o seu uso.

    • lmx says:

      +1,

      Nesses casos que o José Simões reporta, podemos fazer uma macro para o preprocessador, definindo o termo NULL no inicio do ficheiro, e temos o problema resolvido(é assim que é feito no c89 uma macro em diversos ficheiros, no entanto o normal deveria ser em stddef.h, mas existem diversos locais como stdio.h, etc) 😉

      Isto, para as ferramentas de compilação com preprocessador de texto, e que aceitem macros…caso contrario, somos obrigados a usar 0 é bem verdade.. 😉

      É um bom comentário o seu 😉 , porque se levarmos o código para outro ambiente, a coisa pode não funcionar a primeira e garanti-mos desde logo a portabilidade… 😉

Deixe um comentário

O seu endereço de email não será publicado.

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

Aviso: Todo e qualquer texto publicado na internet através deste sistema não reflete, necessariamente, a opinião deste site ou do(s) seu(s) autor(es). Os comentários publicados através deste sistema são de exclusiva e integral responsabilidade e autoria dos leitores que dele fizerem uso. A administração deste site reserva-se, desde já, no direito de excluir comentários e textos que julgar ofensivos, difamatórios, caluniosos, preconceituosos ou de alguma forma prejudiciais a terceiros. Textos de caráter promocional ou inseridos no sistema sem a devida identificação do seu autor (nome completo e endereço válido de email) também poderão ser excluídos.