Saindo dos pesadelos com ponteiros

Geralmente meio acadêmico da uma explicação de ponteiros deixando todos
enrolados com apenas o básico , O que faz todos desviar do caminho dos ponteiros ,
os poucos que usam são aqueles que tem sido autodidata ou fizeram algum curso,
Bom alguns livros tem exemplos bons de ponteiros como no livro Ansi C do
K&R, entretanto a falta de popularidade de tais dicas torna tal assunto meio obscuro…

*Perguntas frenéticas
Por que usar ponteiros ?
–Desempenho e maior manipulação dos dados
E se eu não usar ?
–Na depuração de códigos STACK é bem complicada comparada com HEAP,
no tratamento de dados gigantes poderá ter algumas Traps Malditas!
freddy
Outro ponto interessante,uma das diferenças de 64bit para 32bit, tanto em
64 como 32 tem 32bit em int , entretanto ponteiro tem 64bit em 64bit e em
32bit tem 32bit, reflita…

O que é ponteiro ?
Nada mais é que uma refêrencia , um tipo de dado que armazena um endereço.

Vamos a um exemplo básico para depois ver algo complexo

#include <stdio.h>
#include <string.h>

int main()
{
// ponteiro com int
 int *x,*y;

// fazemos o casting para ponteiro de int
 x=(int *)256;	
 y=(int *)256;
// casting para int antes da adição
 printf("%d \n",((int)x)+((int)y));
 
 puts("digite um numero para adicao com y...");
 scanf("%d",&x);
 printf("%d \n",((int)x)+((int)y));

// ponteiro com strings...
 char *word;

 word="ola";
 puts(word);
 word="lol";
 puts(word);
// 0[l] 1[o] 2[l]   word[2] logo temos "l"
 printf("char: %c \n",*(word+2));

 return 0;
}

vamos entender algumas práticas comuns de se ver depois e partir para exemplos

 int i           //Int variável 'i'
 int *p          //'P' ponteiro para um int
 int a[]         //Matriz 'a' de Int
 int f()         //'F' função com valor de retorno do tipo int
 int **p         //'Pp' ponteiro para um ponteiro para um int
 int (*pa)[]     //'Pa' ponteiro para um array de int
 int (*pf)()     //pf ponteiro para uma função com valor de retorno int
 int *p[]       //Array 'p' de ponteiros para um int
 int *var()       //Função "var", que retorna um ponteiro para um int
 int ***var       //'var' ponteiro para um ponteiro para um ponteiro para um int
 int (**var)[]  //'var' ponteiro para um ponteiro para um array de int
 int (**var)()  //'var' ponteiro para um ponteiro para uma função com valor de retorno do tipo int
 int *(*c)[]  //'c' ponteiro para uma matriz de ponteiros para um int
 int *(*c)()  //"c 'ponteiro para uma função com valor de retorno do tipo ponteiro para um int
 int **app[]    //'App' ponteiro para um ponteiro para uma matriz de ponteiros para um int
 int (*b[])[] //Uma série de 'b' ponteiros para um array de int
 int (*c[])() /Um array 'c' ponteiros para uma função com valor de retorno do tipo int
 int ***fpp()   //"Fpp 'função que retorna um ponteiro para um ponteiro para um ponteiro para um int
 int (*fpa())[] //Função 'fpa ", que retorna um ponteiro para um array de int
 int (*fpf())() //"FPF" função que retorna um ponteiro para uma função com valor de retorno int

Fique calmo não é para decorar , tenha em mente leitura da esquerda para direita,
e sempre começando pelo nome da variável…

Uma prática muito comum em C é usar void pointer, para muitos que estão
iniciando não é normal se ver, Entretanto estudando códigos de terceiros
pode-se ver muito , usar ponteiro colabora no desempenho e o código em
Assembly gerado fica menor de fato,um “disassemble main” no GDB pode te dar ponto
empírico.

um exemplo vale mais do que mil palavras

// exemplo void pointer by Cooler_
#include <stdio.h>

//ideia de polimorfismo 
void foo(void *point,int size)
{
// int == 4 bytes
 if(size==sizeof(int))
//tem que fazer casting do ponteiro para STDOUT
  printf("int : %d , bytes: %d\n",*(int *)point,sizeof(point));

// double == 8 bytes
 if(size==sizeof(double))
//casting de novo para o write(1...
  printf("double : %f , bytes: %d\n",*(double *)point,sizeof(double));
}

int main()
{
 int a=64;
 double b=3.14;

 printf("bytes do void : %d\n",sizeof(void));
// & usamos para dizer o endereço da memória de determinada variável
 foo(&a,sizeof(int));
 foo(&b,sizeof(double));

 return 0;
}

outro exemplo seguindo a mesma lógica

#include <stdio.h>
#include <string.h>

typedef struct _myst
{
 int a;
 char b[10];
}myst;

void func(myst *mt)
{
 printf("resposta %d %s \n",mt->a,mt->b);
}

int main()
{
 void (*resposta)(void *);

 myst x;
 x.a=4;
 strncpy(x.b,"1234",8);
 resposta = (void*)func;
 resposta(&x);

 return 0;
}

Outra prática muito vista é o “ponteiro de arrays para funções“,
vejamos terceiro exemplo:

// example pointer of arrays to function by Cooler_
#include <stdio.h>
#include <malloc.h>

void foo1(int x)
{
 printf("int: %d\n",x);
}

void foo2(int x)
{
 printf("num: %d\n",x);
}

void foo3(int z)
{
 printf("result %d\n",z*z);
}

void func2func(void (*fp)(void *), void *q) 
{
  fp(q);
}

int main()
{
//se a função tiver mais de um argv use "," (int,char...
 void (**list)(int);
//alocamos 3 endereços na heap
 list=(void *)malloc(3*sizeof(void *));

 list[0]=foo1;
 list[0](2);
 list[1]=foo2;
 list[1](4);
 list[2]=foo3;
 list[2](8);

 // função para função lol
 func2func(foo2, 4);

 free(list);
 return 0;
}

outro exemplo usando função com argumento para função

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define w printf 
#define MAX_BUF 128 
#define array_num(array) (sizeof(array) / sizeof *(array))
   
void bubble(void *p, int width, int N,int(*fptr)(const void *, const void *));
int compara_letras(const void *m, const void *n);
int compara_numeros(const void *m, const void *n);
      
int main()
{
 int lista[]={4,2,1,5,3,8,10,9,0,45};
 char nomes[6][20] = {"Madruga","Arara","Zebra","Elefante","Babaca","Gato"};
 short i;
    
 for(i=0; i<=array_num(lista)-1; i++) 
  w("%d\n",lista[i]);
 for(i=0; i<=array_num(nomes)-1; i++) 
  w("%s\n",nomes[i]);
 w("--------------\nagora dando buble sort nas listas\n");
 bubble(lista, 4, 10, compara_numeros);
 bubble(nomes, 20, 6, compara_letras);    
 for(i=0; i<=9; i++) 
  w("%d\n",lista[i]);
 for(i=0; i<=5; i++)
  w("%s\n",nomes[i]);

 return 0;
}

// função com argumento para função 
void bubble(void *p, int width, int N, int(*fptr)(const void *, const void *))
{
 int i, j, k;
 unsigned char buf[MAX_BUF];
 unsigned char *bp = p;
  for(i = N-1; i >= 0; i--)
  {
   for(j = 1; j <= i; j++)
   {
//repare que fptr é a função escolhida pelo usuário
    k = fptr((void *)(bp + width*(j-1)), (void *)(bp + j*width));
    if(k > 0)
    {
     memcpy(buf, bp + width*(j-1), width);
     memcpy(bp + width*(j-1), bp + j*width , width);
     memcpy(bp + j*width, buf, width);
    }
   }
  }
}
//comparando letras graças "strcmp" função da lib "string.h"
  int compara_letras(const void *m, const void *n)
  {
   char *m1 = (char *)m;
   char *n1 = (char *)n;
   return (strcmp(m1,n1));
  }
//comparando numeros
  int compara_numeros(const void *m, const void *n)
  {
   long *m1, *n1;
   m1 = (long *)m;
   n1 = (long *)n;
   return (*m1 > *n1);
  }

outro exemplo arrays tridimensionais com ponteiros

/*
 *   Explanação arrays tridimensionais com Ponteiros
 *
 *       
 *
 * c00f3r[at]gmail[dot]com
 * by Cooler_
 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
/* array tridimensional 
 * 
 * [][][]
 * | | |_posição do caracter, todos caracter formam 1 palavra
 * | |___número da posição onde esta a palavra
 * |____ número da lista de palavras a usar
 *
 
 */
//  produto por 2 de char** pois vamos fazer 2 listas de palavras
 char ***lists=(char ***)malloc( 2*sizeof(char **)   );

//produto por 3 em char* pq vamos usar 3 palavras
 *(lists+0)=(char **)malloc(3*sizeof(char *));
// pode-se fazer tb lists[0][0]="ola"
 *(*(lists+0)+0)="ola";
 *(*(lists+0)+1)="Yay";
 *(*(lists+0)+2)="lol";

 *(lists+1)=(char **)malloc(3*sizeof(char *));
 *(*(lists+1)+0)="epic";
 *(*(lists+1)+1)="let";
 *(*(lists+1)+2)="omg";

 fprintf(stdout," %s \n %s \n %c\n",lists[0][2],lists[1][0],lists[0][0][1]);
/* mostrando uma saida qualquer 
 repare o terceiro elemento palavra "ola" segunda letra "l"

lists[0][0][1]='l'
            |
 [o][l][a] _|
  0  1  2
*/

// usar free() onde usou malloc() para liberar memória HEAP
 free(lists[0]);
 free(lists[1]);
 free(lists);

// caso use windows coloque um pause aqui no final ;-)
 return 0;
}

tem muitas dicas sobre o mesmo por ai,
mas vou dar uma sugestão de leitura
caso queira melhorar ainda mais em ponteiros
famoso livro da truta :-)
expert C

espero ter ajudado ;-)

Comments are closed.