Aritmética de ponteiros

Publicado por João Marcos Menezes 01/05/2008 (última atualização em 09/03/2012)

[ Hits: 10.873 ]

Download ponteiro.c

Download arit.c (versão 2)




Este script é um exemplo simples de aritmética de ponteiros.

Tem a finalidade de mostrar o "caminho das pedras" sobre este assunto, mostra alguns exemplos do uso básico.

Também tem um exemplo do principal cuidado a ser tomado quando utilizar aritmética de ponteiros que se não for controlada pode "detonar" com outras partes da memória.

  



Versões atualizadas deste script

Versão 2 - Enviado por João Marcos Menezes em 08/03/2012

Changelog: Correções

Download arit.c


Esconder código-fonte

#include "stdio.h"

typedef struct estrutura {
   int tipo;
   char valor[10];
} estrut;

char * charToHex(char carac);

int main(int argc, char * argv[])
{

   // Vamos criar um ponteiro para um caractere alocando 10 bytes
   char * string = (char *) malloc(sizeof(char) * 10);

   // Agora vamos gravar 10 bytes
   strcpy(string, "ABCDEFGHIJ");

   // Aqui vamos criar um outro ponteiro, que irá apontar para o mesmo
   // endereço inicial
   char * pontAritString = string;
   // E vamos fazer um loop de 10 vezes (para imprimir os 10 caracteres)
   for (int i = 0; i < 10; i++) {
      printf("%c", *pontAritString);

      // Aqui estaremos aplicando a aritmética de ponteiro, onde estaremos 
      // somando 1 do tipo do ponteiro, ou seja avançando 1 byte (pois é um ponteiro para
      // caracteres)
      pontAritString++;
   }

   // Depois que avançamos 10 posições o valor daquele endereço será um byte 0 (ou nulo)
   if (*pontAritString == '{FONTE}') {
      printf("\n%s\n", "NULO");
   }

   // CUIDADO: Se a aritmética for aplicada de maneira errada, iremos enxergar a próxima posição
   // da memória que poderá ser parte de outro programa inclusive. Se você começar a mudar os valores
   // é aqui que os problemas começam
   pontAritString++;

   // Vamos imprimir o valor inteiro do caractere para não detonar com o terminal
   printf("%d", (int) *pontAritString);

   // Outro exemplo legal é que a aritmética é aplicada na estrutura
   // Veja o exemplo, armazenando 10 estruturas
   estrut * testeEstrut = (estrut *) malloc(sizeof(estrut) * 10);
   
   // Vamos criar uma outra variavel ponteiro para o inicio da estrutura
   estrut * pontTesteEstrut = testeEstrut;
   // Vamos preencher 10 valores
   for (int i = 0; i < 10; i++) {
      pontTesteEstrut->tipo = i;
      char tmp[10];
      sprintf(tmp, "String: %d", i);
      strcpy(pontTesteEstrut->valor, tmp);
      pontTesteEstrut++;
   }

   // E agora vamos imprimir os valores preenchidos
   // Lembrando que temos de apontar novamente para o endereço inicial
   pontTesteEstrut = testeEstrut;
   for (int i = 0; i < 10; i++) {
      printf("\nTipo: %d - Valor: %s", pontTesteEstrut->tipo, pontTesteEstrut->valor);
      pontTesteEstrut++;
   }

   // Outra coisa interessante é que podemos aplicar a aritmética ou cast do tipo de dados
   // a partir de outros dados (afinal tudo são bytes)
   // Veja o exemplo:
   signed int * pontInteiro = (signed int *) malloc(sizeof(signed int));
   // Vamos armazenar o número 158255   
   *pontInteiro = 158255;

   // Agora vamos fazer a aritmética utilizando uma estrutura de char (1 byte)
   // Serão impressos os bytes do número 158255 que são: 02 6A 2F, na forma
   // de armazenamento de inteiro será impresso 2F 6A 02, ou seja, os bytes
   // de armazenamento do número 158255
   char * pontCharInteiro = (char *) pontInteiro;
   printf("\nSerão impressos os bytes do número:\n");
   while (*pontCharInteiro != '{FONTE}') {
      printf("%s\n", charToHex(*pontCharInteiro));

      // aqui avançamos 1 byte
      pontCharInteiro++;
   }


   return 0;
}

char * charToHex(char carac) {
   // Tosco, poderia ser muitoooo melhor
   char * ret = new char[2];
   char hexa[16];
   hexa[0] = '0';
   hexa[1] = '1';
   hexa[2] = '2';
   hexa[3] = '3';
   hexa[4] = '4';
   hexa[5] = '5';
   hexa[6] = '6';
   hexa[7] = '7';
   hexa[8] = '8';
   hexa[9] = '9';
   hexa[10] = 'A';
   hexa[11] = 'B';
   hexa[12] = 'C';
   hexa[13] = 'D';
   hexa[14] = 'E';
   hexa[15] = 'F';
   int comp = 0;
   int val1;
   int val2;
   for (int x = 0; x < 16; x++) {
      val1 = x;
      for (int y = 0; y < 16; y++) {
         val2 = y;
         if ((char) comp == carac) {
            ret[0] = hexa[val1];
            ret[1] = hexa[val2];
            ret[2] = '{FONTE}';
            y = 16;
            x = 16;
            break;
         }
         comp ++;
      }
   }
   return ret;
}


Scripts recomendados

Identificando Palíndromos

Passando uma matriz para funcao

Árvore binária - Pré-ordem

Retorna o tempo ocioso em uma sessão do X

Pilha


  

Comentários
[1] Comentário enviado por HelioCampos em 02/05/2008 - 08:16h

Estão faltando declarações de bibliotecas e vc está tentando por 11 caracteres em uma variável com 10 espaços...

[2] Comentário enviado por stremer em 06/05/2008 - 09:37h

comiti alguns erros bobos (stl e buffers grandes no dia a dia da isso), mas abaixo pode ser encontrada a versão corrigida (que já enviei ao VOL).

[3] Comentário enviado por stremer em 06/05/2008 - 14:59h

comiti alguns erros bobos (stl e buffers grandes no dia a dia da isso), mas abaixo pode ser encontrada a versão corrigida (que já enviei ao VOL).

[4] Comentário enviado por stremer em 06/05/2008 - 15:19h

Este código windows não era para estar aqui, mas o VOL publicou, e vou mandar outra mensagem para retira-los e deixar somente a versão linux.

Segue abaixo o código corrigido (linux). Como não consigo alterar o código do vol estarei mandando um e-mail solicitando a correção do script. Tentei eliminar o problema do char 0 criando um int 0 para comparar com o null (ou barra zero) que é bloqueado pelo VOL. Acrescentei os includes que o amigo sugeriu mesmo o meu gcc não precisando delas (descobri que era umas globais da minha instalação linux e nem me toquei na hora que escrevi o código), então acrescentei.

----------------- pont.c ----------------
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

typedef struct estrutura {
int tipo;
char valor[10];
} estrut;

static int CONST_ZERO = 0;

char * charToHex(char carac);

int main(int argc, char * argv[])
{

// Vamos criar um ponteiro para um caractere alocando 11 bytes
char * string = (char *) malloc(sizeof(char) * 11);

// Agora vamos gravar 10 bytes
strcpy(string, "ABCDEFGHIJ");

// Aqui vamos criar um outro ponteiro, que irá apontar para o mesmo
// endereço inicial
char * pontAritString = string;
// E vamos fazer um loop de 10 vezes (para imprimir os 10 caracteres)
int i = 0;
for (i = 0; i < 10; i++) {
printf("%c", *pontAritString);

// Aqui estaremos aplicando a aritmética de ponteiro, onde estaremos
// somando 1 do tipo do ponteiro, ou seja avançando 1 byte (pois é um ponteiro para
// caracteres)
pontAritString++;
}

// Depois que avançamos 10 posições o valor daquele endereço será um byte 0 (ou nulo)
if (*pontAritString == CONST_ZERO) {
printf("\n%s\n", "NULO");
}

// CUIDADO: Se a aritmética for aplicada de maneira errada, iremos enxergar a próxima posição
// da memória que poderá ser parte de outro programa inclusive. Se você começar a mudar os valores
// é aqui que os problemas começam
pontAritString++;

// Vamos imprimir o valor inteiro do caractere para não detonar com o terminal
printf("%d", (int) *pontAritString);

// Outro exemplo legal é que a aritmética é aplicada na estrutura
// Veja o exemplo, armazenando 10 estruturas
estrut * testeEstrut = (estrut *) malloc(sizeof(estrut) * 10);

// Vamos criar uma outra variavel ponteiro para o inicio da estrutura
estrut * pontTesteEstrut = testeEstrut;
// Vamos preencher 10 valores
for (i = 0; i < 10; i++) {
pontTesteEstrut->tipo = i;
char tmp[10];
sprintf(tmp, "String: %d", i);
strcpy(pontTesteEstrut->valor, tmp);
pontTesteEstrut++;
}

// E agora vamos imprimir os valores preenchidos
// Lembrando que temos de apontar novamente para o endereço inicial
pontTesteEstrut = testeEstrut;
for (i = 0; i < 10; i++) {
printf("\nTipo: %d - Valor: %s", pontTesteEstrut->tipo, pontTesteEstrut->valor);
pontTesteEstrut++;
}

// Outra coisa interessante é que podemos aplicar a aritmética ou cast do tipo de dados
// a partir de outros dados (afinal tudo são bytes)
// Veja o exemplo:
signed int * pontInteiro = (signed int *) malloc(sizeof(signed int));
// Vamos armazenar o número 158255
*pontInteiro = 158255;

// Agora vamos fazer a aritmética utilizando uma estrutura de char (1 byte)
// Serão impressos os bytes do número 158255 que são: 02 6A 2F, na forma
// de armazenamento de inteiro será impresso 2F 6A 02, ou seja, os bytes
// de armazenamento do número 158255
char * pontCharInteiro = (char *) pontInteiro;
printf("\nSerao impressos os bytes do numero:\n");
for (i = 0; i < sizeof(signed int); i++) {
printf("%s\n", charToHex(*pontCharInteiro));

// aqui avançamos 1 byte
pontCharInteiro++;
}


return 0;
}

char * charToHex(char carac) {
// Tosco, poderia ser muitoooo melhor
char * ret = (char *) malloc(sizeof(char) * 3);
char hexa[16];
hexa[0] = '0';
hexa[1] = '1';
hexa[2] = '2';
hexa[3] = '3';
hexa[4] = '4';
hexa[5] = '5';
hexa[6] = '6';
hexa[7] = '7';
hexa[8] = '8';
hexa[9] = '9';
hexa[10] = 'A';
hexa[11] = 'B';
hexa[12] = 'C';
hexa[13] = 'D';
hexa[14] = 'E';
hexa[15] = 'F';
int comp = 0;
int val1;
int val2;
int x = 0;
int y = 0;
for (x = 0; x < 16; x++) {
val1 = x;
for (y = 0; y < 16; y++) {
val2 = y;
if ((char) comp == carac) {
ret[0] = hexa[val1];
ret[1] = hexa[val2];
ret[2] = CONST_ZERO;
y = 16;
x = 16;
break;
}
comp ++;
}
}
return ret;
}

----------------- fim pont.c --------

[5] Comentário enviado por stremer em 06/05/2008 - 15:31h

Este foi meu primeiro script e vi que o sistema do vol detona com algumas coisas do código. No próximo tomarei mais cuidado.
Obrigado a todos!


Contribuir com comentário