ELT048 - SOE



Ponteiros, Structs e Buffers Circulares

              Rodrigo Almeida
       Universidade Federal de Itajubá
Ponteiros
Ponteiros
●   São variáveis que guardam o endereço (localização)
    de memória.
    ●   Nestes endereços da memória é possível colocar
        valores e utilizá-los.
●   Os tipos de valores colocados nos endereços de
    memória são definidos na declaração de um ponteiro.
    ●   É esse tipo que indica ao compilador a quantidade de
        memória necessária para armazenar os valores.
●   Uma variável do tipo ponteiro aponta para uma
    variável de um determinado tipo (char, int, float,
    double, . . .).
Ponteiros
●   É necessário na         ●   Sintaxe:
    declaração de um            tipo *nomeVariavel;
    ponteiro, especificar
    para qual tipo de
    variável ele irá
    apontar.
●   Os ponteiros são
    declarados com um
    * antes do nome da
    variável.
Ponteiros
int *aux;           ●   aux, temp e pont são
float *temp;            variáveis que
                        armazenam endereços
char *pont;             de memória e não
                        valores do tipo int, float
                        ou char.
                    ●   * é usado quando
                        deseja-se acessar o
                        valor que está na
                        posição de memória e
                        não ao endereço da
                        memória.
Ponteiros
Ponteiros
●   Operador &:                        ●   Operador *:
    ●   Obtém sempre o                     ●   O operador * faz o
        endereço de uma                        contrário do operador
        variável                               &.
    ●   Como os ponteiros                  ●   Dado um ponteiro, o
        também são variáveis                   operador * acessa o
        eles também ocupam                     conteúdo apontado
        memória.                               por ele.
        –   Pode-se obter o
            endereço do ponteiro
            e ter ponteiros para
            ponteiros (múltiplos *).
Ponteiros
●   Simbolo &:            ●   Simbolo *:
    ●   “endereço de”         ●   “derreferenciando”
    ●   “salvo em”            ●   “através de”
                              ●   “apontado por”
Exemplo
#include <stdio.h>

int main(int argc, char *argv[]){
   int x=10;
   int *p1=&x; //ponteiro para um inteiro
   printf("x = %dnn", x);
   *p1=20; //ou p1[0]=20;
   printf("p1 = %un", p1);
   printf("x = %dn", x);
   printf("*p1 = %dn", *p1);
   printf("p1[0] = %dnn", p1[0]);
   return 0;
} //end main
Passagem de parâmetros
●   As funções em linguagem C podem receber
    vários parâmetros e pode retornar um.
●   O método de envio dos parâmetros pode
    ser feito na pilha ou nos registradores.
    ●   A pilha permite que diversos parâmetros sejam
        passados de uma única vez
    ●   Os registros possuem menor overhead, sendo
        portanto mais rápidos e com menor tamanho
        de código
Passagem de parâmetros
●   No envio, os parâmetros são copiados para uma
    variável temporária, de modo que as alterações
    em seu valor são perdidas após o fim da função.
    ●   A variável inicial não é alterada
●   Para evitar esta situação é comum realizar a
    passagem de parâmetro por referência.
●   Na passagem por referência é passado o
    endereço da variável de modo que a função
    consiga alterar o valor da variável original.
void incrementa(int a){
  a += 1;
}

int main(int argc, char *argv[]){
  int x = 10;

    incrementa(x);

    return 0;
}
Rotina Principal           Função



void main(void){
  int x = 10;

    incrementa(x);        void incrementa(int a)
                          {
                            a+=1;
                            return;
                          }
    return 0;
}
Rotina Principal       Função         Variáveis

void main(void)
{
  int x = 10;                               x=10


    inc(x);            void inc(int a){
                         a += 1;
                         return;
                       }

    return 0;
}
Rotina Principal       Função         Variáveis

void main(void)
{
  int x = 10;                               x=10
                                            a=10
    inc(x);            void inc(int a){
                         a += 1;
                         return;
                       }

    return 0;
}
Rotina Principal       Função         Variáveis

void main(void)
{
  int x = 10;                               x=10
                                            a=11
    inc(x);            void inc(int a){
                         a += 1;
                         return;
                       }

    return 0;
}
Rotina Principal       Função         Variáveis

void main(void)
{
  int x = 10;                               x=10
                                          descartado
    inc(x);            void inc(int a){
                         a += 1;
                         return;
                       }

    return 0;
}
void incrementaptr(int* a){
   (*a) += 1;
}

int main(int argc, char *argv[]){
    int x = 10;

    incrementaptr(&x);

    return 0;
} //end main
Rotina Principal       Função        Variáveis

void main(void)
{
  int x = 10;                              x=10


    incptr(&x);        void incptr
                             (int* a){
                         (*a) += 1;
                         return;
                       }
    return 0;
}
Rotina Principal       Função        Variáveis

void main(void)
{
  int x = 10;                              x=10
                                         temp=&x
    incptr(&x);        void incptr
                             (int* a){
                         (*a) += 1;
                         return;
                       }
    return 0;
}
Rotina Principal       Função        Variáveis

void main(void)
{
  int x = 10;                              x=10
                                           a=&x
    incptr(&x);        void incptr
                             (int* a){
                         (*a) += 1;
                         return;
                       }
    return 0;
}
Rotina Principal       Função        Variáveis

void main(void)
{
  int x = 10;                              x=11


    incptr(&x);        void incptr
                                           a=&x      *
                             (int* a){
                         (*a) += 1;
                         return;
                       }
    return 0;
}
Rotina Principal       Função        Variáveis

void main(void)
{
  int x = 10;                              x=11
                                         descartado
    incptr(&x);        void incptr
                             (int* a){
                         (*a) += 1;
                         return;
                       }
    return 0;
}
Passagem de parâmetros
●   A passagem de parâmetros por referência
    permite que uma função “retorne” mais de
    um parâmetro por vez.
●   Isto é feito passando-se uma variável via
    referência para que a função possa
    escrever nela.
Structs
●   As estruturas (structs) são a ferramenta
    pela qual o programador pode agrupar
    diversas variáveis de tipos diferentes num
    mesmo conjunto.
●   Utilizando-se a diretiva typedef é possível
    definir-se um novo tipo de variável.
Structs
typedef struct{
  char titulo[30];
  char producao[20];
  char dataCompra[8];
  int temporada;
  float preco;
}t_serietv;


t_serietv s1 = {"Big Bang Theory", "Warner",
                "25/05/10", 3, 55.50};
strcpy(s1.titulo,"The Big Bang Theory");
strcpy(s1.producao, "Warner Bros");
s1.temporada = 6;
printf("A serie foi produzida pela %s,", s1.producao);
printf(" e esta na temporada %dn", s1.temporada);
Structs
●   O acesso dos         typedef struct{
                            char nome[20];
    membros internos        int idade;
    de estruturas        }t_aluno;
    apontadas por
    ponteiros pode ser   t_aluno *a1;
    feito através do     (*a1).nome = "Joao";
    operador ->          (*a1).idade = 18;

                         a1->nome = "Joao";
                         a1->idade = 18;
Buffers
●   Buffers são regiões de memória para
    armazenamento temporário de
    informações.
●   Podem ser implementados em SW ou HW.
●   Muito comuns em protocolos de
    comunicação.
Buffers
●   Buffers circulares auxiliam na
    implementação de filas do tipo FIFO (first
    in, first out)
●   Em geral são implementados em cima de
    um vetor com funções para a manipulação
    deste.
●   É necessário possuir ponteiros/variáveis
    que indiquem o começo e fim do buffer.
●   Deve-se tomar cuidado na escolha
Exercício
●   Implementar um buffer circular
●   Utilizar um vetor de 10 posições
●   Cada elemento do vetor é uma estrutura
    com duas variáveis
    ●   char NomeDoProcesso
    ●   int Prioridade
●   Criar uma função para adicionar novos
    elementos e uma para retirar os mais
    antigos.
Ponteiros para void
●   Aponta para uma região de memória sem
    especificar o tipo.
●   Não pode ser utilizado sem casting
●   Abstração que permite ao programador
    passar parâmetros de diferentes tipos para
    a mesma função.
    ●   A função que os receber deve saber como
        tratar cada tipo.
Ponteiros para void

char *name = "Paulo";

double weight = 87.5;

unsigned int children = 3;

void main (void){
   //não confundir com printf
   print(0, name);
   print(1, &weight);
   print(2, &children);
}
Ponteiros para void
void print(int option; void *parameter){
  switch(option){
     case 0:
        printf("%s",(char*)parameter);
     break;
     case 1:
        printf("%f",*((double*)parameter));
     break;
     case 2:
        printf("%d",*((unsigned int*)parameter));
     break;
  }
}
Exercício (cont)
●   Implementar um buffer circular
●   Utilizar um vetor de 10 posições
●   Cada elemento do vetor é uma estrutura com
    duas variáveis
    ●   char tipo
    ●   void* ptr
●   Criar uma função para adicionar novos elementos
    e uma para retirar os mais antigos.
    ●   Add(char tipo, void* var);
    ●   Remove(void);

Conceitos de ponteiros struct e buffers

  • 1.
    ELT048 - SOE Ponteiros,Structs e Buffers Circulares Rodrigo Almeida Universidade Federal de Itajubá
  • 2.
  • 3.
    Ponteiros ● São variáveis que guardam o endereço (localização) de memória. ● Nestes endereços da memória é possível colocar valores e utilizá-los. ● Os tipos de valores colocados nos endereços de memória são definidos na declaração de um ponteiro. ● É esse tipo que indica ao compilador a quantidade de memória necessária para armazenar os valores. ● Uma variável do tipo ponteiro aponta para uma variável de um determinado tipo (char, int, float, double, . . .).
  • 4.
    Ponteiros ● É necessário na ● Sintaxe: declaração de um tipo *nomeVariavel; ponteiro, especificar para qual tipo de variável ele irá apontar. ● Os ponteiros são declarados com um * antes do nome da variável.
  • 5.
    Ponteiros int *aux; ● aux, temp e pont são float *temp; variáveis que armazenam endereços char *pont; de memória e não valores do tipo int, float ou char. ● * é usado quando deseja-se acessar o valor que está na posição de memória e não ao endereço da memória.
  • 6.
  • 7.
    Ponteiros ● Operador &: ● Operador *: ● Obtém sempre o ● O operador * faz o endereço de uma contrário do operador variável &. ● Como os ponteiros ● Dado um ponteiro, o também são variáveis operador * acessa o eles também ocupam conteúdo apontado memória. por ele. – Pode-se obter o endereço do ponteiro e ter ponteiros para ponteiros (múltiplos *).
  • 8.
    Ponteiros ● Simbolo &: ● Simbolo *: ● “endereço de” ● “derreferenciando” ● “salvo em” ● “através de” ● “apontado por”
  • 9.
    Exemplo #include <stdio.h> int main(intargc, char *argv[]){ int x=10; int *p1=&x; //ponteiro para um inteiro printf("x = %dnn", x); *p1=20; //ou p1[0]=20; printf("p1 = %un", p1); printf("x = %dn", x); printf("*p1 = %dn", *p1); printf("p1[0] = %dnn", p1[0]); return 0; } //end main
  • 10.
    Passagem de parâmetros ● As funções em linguagem C podem receber vários parâmetros e pode retornar um. ● O método de envio dos parâmetros pode ser feito na pilha ou nos registradores. ● A pilha permite que diversos parâmetros sejam passados de uma única vez ● Os registros possuem menor overhead, sendo portanto mais rápidos e com menor tamanho de código
  • 11.
    Passagem de parâmetros ● No envio, os parâmetros são copiados para uma variável temporária, de modo que as alterações em seu valor são perdidas após o fim da função. ● A variável inicial não é alterada ● Para evitar esta situação é comum realizar a passagem de parâmetro por referência. ● Na passagem por referência é passado o endereço da variável de modo que a função consiga alterar o valor da variável original.
  • 12.
    void incrementa(int a){ a += 1; } int main(int argc, char *argv[]){ int x = 10; incrementa(x); return 0; }
  • 13.
    Rotina Principal Função void main(void){ int x = 10; incrementa(x); void incrementa(int a) { a+=1; return; } return 0; }
  • 14.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=10 inc(x); void inc(int a){ a += 1; return; } return 0; }
  • 15.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=10 a=10 inc(x); void inc(int a){ a += 1; return; } return 0; }
  • 16.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=10 a=11 inc(x); void inc(int a){ a += 1; return; } return 0; }
  • 17.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=10 descartado inc(x); void inc(int a){ a += 1; return; } return 0; }
  • 18.
    void incrementaptr(int* a){ (*a) += 1; } int main(int argc, char *argv[]){ int x = 10; incrementaptr(&x); return 0; } //end main
  • 19.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=10 incptr(&x); void incptr (int* a){ (*a) += 1; return; } return 0; }
  • 20.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=10 temp=&x incptr(&x); void incptr (int* a){ (*a) += 1; return; } return 0; }
  • 21.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=10 a=&x incptr(&x); void incptr (int* a){ (*a) += 1; return; } return 0; }
  • 22.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=11 incptr(&x); void incptr a=&x * (int* a){ (*a) += 1; return; } return 0; }
  • 23.
    Rotina Principal Função Variáveis void main(void) { int x = 10; x=11 descartado incptr(&x); void incptr (int* a){ (*a) += 1; return; } return 0; }
  • 24.
    Passagem de parâmetros ● A passagem de parâmetros por referência permite que uma função “retorne” mais de um parâmetro por vez. ● Isto é feito passando-se uma variável via referência para que a função possa escrever nela.
  • 25.
    Structs ● As estruturas (structs) são a ferramenta pela qual o programador pode agrupar diversas variáveis de tipos diferentes num mesmo conjunto. ● Utilizando-se a diretiva typedef é possível definir-se um novo tipo de variável.
  • 26.
    Structs typedef struct{ char titulo[30]; char producao[20]; char dataCompra[8]; int temporada; float preco; }t_serietv; t_serietv s1 = {"Big Bang Theory", "Warner", "25/05/10", 3, 55.50}; strcpy(s1.titulo,"The Big Bang Theory"); strcpy(s1.producao, "Warner Bros"); s1.temporada = 6; printf("A serie foi produzida pela %s,", s1.producao); printf(" e esta na temporada %dn", s1.temporada);
  • 27.
    Structs ● O acesso dos typedef struct{ char nome[20]; membros internos int idade; de estruturas }t_aluno; apontadas por ponteiros pode ser t_aluno *a1; feito através do (*a1).nome = "Joao"; operador -> (*a1).idade = 18; a1->nome = "Joao"; a1->idade = 18;
  • 28.
    Buffers ● Buffers são regiões de memória para armazenamento temporário de informações. ● Podem ser implementados em SW ou HW. ● Muito comuns em protocolos de comunicação.
  • 29.
    Buffers ● Buffers circulares auxiliam na implementação de filas do tipo FIFO (first in, first out) ● Em geral são implementados em cima de um vetor com funções para a manipulação deste. ● É necessário possuir ponteiros/variáveis que indiquem o começo e fim do buffer. ● Deve-se tomar cuidado na escolha
  • 30.
    Exercício ● Implementar um buffer circular ● Utilizar um vetor de 10 posições ● Cada elemento do vetor é uma estrutura com duas variáveis ● char NomeDoProcesso ● int Prioridade ● Criar uma função para adicionar novos elementos e uma para retirar os mais antigos.
  • 31.
    Ponteiros para void ● Aponta para uma região de memória sem especificar o tipo. ● Não pode ser utilizado sem casting ● Abstração que permite ao programador passar parâmetros de diferentes tipos para a mesma função. ● A função que os receber deve saber como tratar cada tipo.
  • 32.
    Ponteiros para void char*name = "Paulo"; double weight = 87.5; unsigned int children = 3; void main (void){ //não confundir com printf print(0, name); print(1, &weight); print(2, &children); }
  • 33.
    Ponteiros para void voidprint(int option; void *parameter){ switch(option){ case 0: printf("%s",(char*)parameter); break; case 1: printf("%f",*((double*)parameter)); break; case 2: printf("%d",*((unsigned int*)parameter)); break; } }
  • 34.
    Exercício (cont) ● Implementar um buffer circular ● Utilizar um vetor de 10 posições ● Cada elemento do vetor é uma estrutura com duas variáveis ● char tipo ● void* ptr ● Criar uma função para adicionar novos elementos e uma para retirar os mais antigos. ● Add(char tipo, void* var); ● Remove(void);