Interagir com ponteiros em C/C++

arrays dinâmicos em C++ | Interagir com ponteiros | Alocação de memória | Ponteiros em C/C++ | Socket server com ESP8266 | Socket server com ESP32 | Socket server com Python | Socket client com ESP32 | Sistema de arquivos no ESP8266

Já tivemos dois artigos sobre o tema, sendo o “Ponteiros em C/C++” e “Alocação de memória em C/C++“. Gradativamente vamos vendo mais sobre ponteiros, dando continuidade de onde paramos no último artigo. Vamos interagir com ponteiros de uma forma diferente: caminhando pelos endereçamentos.

Para quem procura um bom livro de C++, recomendo fortemente o “C++ Primer Plus“, já recomendado outras vezes (porém, leitura em inglês). O meu é impresso, mas tem a versão Kindle, no link desse parágrafo.

Interagir com ponteiros pelo endereço

Vou colocar um exemplo simples, utilizando o tipo char, por utilizar apenas 1 byte.

Quando reservamos memória com a função malloc(), é como se modelássemos um recipiente para comportar determinado volume de líquido. Por essa razão, quando fazemos a reserva especificamos o tipo via casting:

char *teste = (char*) malloc(sizeof(char)*4);

Usaremos esse exemplo para que não fique apenas na teoria, não se preocupe. No momento, vamos tentar entender o que foi feito – adiantando que esse tratamento já foi explicado em outro artigo da série.

Quando declaramos um ponteiro, reservamos uma área de memória para um determinado tipo ou objeto. Minha visão pessoal de ponteiro para um objeto é que, se temos que armazenar algo cujo volume seja maior que uma unidade, ela deve ser feita via ponteiro.

QTimer *timer = new QTimer(this);

Esse é um exemplo de instância de um objeto QTimer, do Qt. Não vamos falar muito de objetos até que chegue o momento certo, mas esse exemplo é para figurar minha forma de pensar.

Não significa que não possamos ter objetos estáticos; aliás, fazemos muito disso com as bibliotecas do Arduino:

WiFiServer sockServer(SOCK_PORT);

A diferença é que para acessar um método do objeto estático utilizamos um ponto (“.“) e para acessar o método através de um ponteiro, utilizamos “->“.

Com variáveis é mais fácil interpretar como vejo. Se queremos guardar uma letra do alfabeto, criamos uma variável do tipo char:

char letter = 'a';

Se queremos guardar uma palavra, criamos um ponteiro para alocar um array de char:

char *teste = (char*) malloc(sizeof(char)*4);

Ou para um caso em que não seja fundamental reservar memória dinamicamente:

char teste[4];

Para acessar os campos, podemos fazer o tradicional apontamento pelo índice ou caminhar pelo endereço de cada índice:

#include <iostream>
#include <cstring>

using namespace std;


int main(){
    char *teste = (char*) malloc(sizeof(char)*4);
    strcpy(teste,"abc"); //copia para a variável de 4 bytes e finaliza com 0.
 
    cout << "valor armazenado: "; 
    cout << teste; //mostra o array completo

    cout << endl << "Valor posicional 1: ";
    cout << teste[1] << endl; // mostra a posição 1, ou seja: b

    cout << "sempre na mesma posicao..." << endl;
    for (uint8_t i=0; i<4;i++){
         cout << *teste; //esse loop vai exibir sempre o que estiver no endereço da reserva de memória
    }

    cout << endl << "Caminhando no endereco:" << endl;

    for (uint8_t i=0; i<4;i++){
        cout << *teste; //exibe o que estiver no endereço...
         teste = teste+1; //...e incrementa o endereço, de modo a deslocar o apontamento do ponteiro
    }
    cout << endl;

    return 0;
}

Já mostrei em outro artigo como compilar. Estou usando Linux, mas para Windows é a mesma coisa, basta ter o g++ instalado. Chamei o programa de “var”. Para compilá-lo, use:

g++ -o var variaveis01.cpp

Ao executá-lo, a saída deve retornar algo como:

Compare com o código para assimilar o que representa cada saída. E, por que andando na mesma posição o ‘a’ foi impresso 4 vezes? Simples: quando fizemos strcpy, colocamos abc\0 no array. São 4 bytes, mas o \0 não é um caractere imprimível, é apenas o índice que indica o final, como se fosse um ponto final. Quando fizemos o loop, o array foi varrido 4 vezes no índice 0, que está armazenando a letra ‘a’, por isso aparece visualmente 1 byte a mais.

Para caminhar pelo endereço, devemos estar seguros da alocação, de outro modo podemos ter resultados inesperados.

Para não ficar cansativo, vou adicionando um conteúdo médio a cada artigo relacionado. Veremos diversas outras manipulações em artigos (provavelmente) semanais sobre o tema.

Acompanhe e até a próxima!

 

Revisão: Ricardo Amaral de Andrade