Jump to content

Eduardo Bittencourt

Membros
  • Posts

    35
  • Joined

  • Last visited

Everything posted by Eduardo Bittencourt

  1. Ponteiros em C Olá, vou fazer um breve resumo do que eu aprendi até agora sobre ponteiros, lembrando que eu não fiz nenhuma formatação, e nem vou me aprofundar neste assunto, até mesmo porque tenho muito o que treinar ainda, se alguém quiser incrementar algo é só falar. 1->Todo ponteiro, pode aponta para algum lugar, e guardar o endereço de memória do dado apontado. O ponteiro tem o tamanho de um inteiro, e ao apontar para um dado, tem o tamanho deste dado. Vale ressaltar, que o tamanho pode variar de acordo o sistema operacional ou arquitetura. #include <stdio.h> int main(void) { char *ptr; printf("%d", sizeof(ptr)); //tamanho de um unsigned inteiro printf("%d", sizeof(*ptr)); //tamanho de um char, porque neste caso ptr está apontando para este tipo de dado return 0; } 2-Pode se dizer que todo array, faz referência a um ponteiro e vice versa. Internamente o compilador considera, que todo nome de um array é um ponteiro para o primeiro índice deste array, e seu tamanho é fixo e linear na memória, que é incrementado em bytes de acordo com o seu tipo. #include <stdio.h> #include <string.h> int main(void) { char nome[] = {'t','e','s','t','e','\0'}; int i; for(i=0; i < strlen(nome); i++) printf("Letra: %c Endereço de memória: %p\n", nome[i], nome[i]); // percorre todo o array e retorna o valor que está em cada posição, e o endereço de mem´´oria // note que só incrementa de 1 byte na memória de forma linear return 0; } 3-Um ponteiro pode apontar diretamente para um array, sem precisar usar o operador de referência &, isso ocorre porque todo nome de um array é um ponteiro, e a primeira posição tem o mesmo endereço de memória do nome da variável, obs: Só tem o mesmo endereço de memória para arrays, e não para ponteiros. ¨#include <stdio.h> int main(void) { char *ptr = "Ponteiro"; // Isso aqui é uma constante estática, o compilador coloca essa variável na seção .rodata, que apenas permite leitura, por isso é uma constante //Obviamente todo array começa no 1 indice, ou seja, para temos todos dados ou lista, como quiser chamar, é necessaria informar apenas o 1 indice printf("%x", &ptr); // Exibe o endereço de memória do ponteiro em hexadecimal printf("%p", ptr); //Exibe o endereço de memória para onde o ponteiro aponta //Nota: O correto seria usar a conversão de formato %p, e não %x. para obter o endereço de memória de um ponteiro. Porque independente de arquitetura vai mostrar de maneira adequada char string[] = "Isso é um array"; //Array de chars, o compilador já faz o trabalho de contar os caracteres, e colocar nullbyte no final printf("%x", &string); // Endereço de memória de string em hexadecimal printf("%p", string); // Endereço de memória para onde string aponta, justamente o mesmo endereço do nome do array ptr = string; // não preciso usar o operador ¨&, porque o nome string é um ponteiro para &string[0]; /*ptr é um atalho para &ptr[0], quando usamos a função printf, ou demais funções, o compilador está na verdade lendo o endereço de memória da variável, isso ocorre quando a váriavel é um array*/ printf("%s", &ptr[0]); return 0; } 4-Operadores: *->Dereferência ¨&->Referência Atalho->*ptr == ptr[0] ambos são a mesma coisa O operador & comercial, retorna o endereço de memória de uma variável, ou até mesma uma função O operador * asterisco, retorna o conteúdo para onde o ponteiro está apontando #include <stdio.h> #include <stdlib.h> /*A função func, nada mais é do que uma tentativa de explicar que não podemos modificar o valor que está no endereço da variável numero[1] Porque não apontamos para o endereço de memória, e sim colocamos o valor que está em numero[1], em x[0]*/ void func(void) { int *x = malloc(sizeof(int)); // aloco 4 bytes do tipo inteiro int numero[5] = {1,2,3,4,5}; *x = numero[1]; printf("Soma do valor do ptr: %d\n", *x+5); numero[1] = 10; printf("%d\n", *x); free(x); } int main(void) { int *x ; int numero[5] = {1,2,3,4,5}; x = &numero[1]; // recebe o endereço de memória de numero[1] , vou ter todo o conteúdo a partir do elemento numero[1] em diante printf("%d\n", *x); /*Ponteiro inicialmente sempre aponta para o começo de um dado, neste caso retorna o contéudo para onde o ponteiro está apontando */ printf("%d\n", *++x); // Incremento, e depois exibe o número 3 numero[1] = 10; printf("%d\n", *(x-1)); /*Estou decrementando 1 na posição, equivalente ao decremento de 4 bytes, não é recomendado usar valores negativos, porque pode trazer problemas de segurança e warnings na compilação.*/ func(); return 0; } 5-Ao criamos um ponteiro, sempre é bom inicializa-lo, pois o ponteiro pode apontar para um endereço de memória inválida ou sem permissão de leitura, causando lixo de memória, e encerrando com o sinal SIGSEGV, para isso não ocorrer, podemos inicializamos com um valor, especificamente 0, que limpa. #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { int *ptr = 0; // Ponteiro aponta para 0, logo temos uma area de memória válida char *pointer = NULL; // Aponta para a constante null // As duas declarações fazem a mesma coisa, aponta para o 0 char *ptr; char nome[256]; memset(nome, 0, sizeof(nome)); / * Escreve na memória o valor 0, para a variável nome, simplificando, inicializei todos os dados da variável nome que é um array*/ } 6-A função memset escreve no endereço de memória um valor, serve para inicializar uma array, ponteiro ou estrutura, enfim. Por isso que é muito utilizado para limpar um buffer, porque pode simplesmente inicializar todos os elementos do array com 0. Parte corrigida graças ao Mercês, no programa abaixo utilizo a função memset pra escrever o byte x no endereço de memória, fiz isso para demonstrar que podemos usar a função memset pra escrever um byte em memória, por em não é a melhor forma, a não ser, se quisermos inicializar um array, nos comentários o Mercês explica a maneira correta #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(void) { char *ptr = malloc(11); // Aloca 11 bytes, 10 bytes para a string, e 1 byte a mais para o nullbyte strcpy(ptr, "aaaaaaaaab"); char *aux = ptr; while (*ptr != 'b') { // percorre o loop até achar a letra b memset(ptr, 'x', sizeof(char)); // escreve o byte 'x' no endereço de memória apontado por ptr (a escrita rola sizeof(char) vezes - no caso aqui é 1) ptr++; // incrementa sizeof(char) bytes no endereço para o qual o ponteiro aponta (seu valor) } puts(aux); free(aux); return 0; } 7-Podemos manipular o endereço de memória de várias formas, uma dessas é quando passamos um argumento do tipo ponteiro na função. Na verdade estamos pegando o seu endereço de memória, e passando para uma função genérica, e com isso mudamos o que tem dentro do endereço de memória, essa função dá se o nome de passagem por referência. Obs: Ao utilizar-se uma função que pede como argumento um ponteiro, não nos obriga a passar uma variável que seja ponteiro, pois o que importa realmente é o endereço de memória, lembre-se que, o nome do ponteiro sempre aponta para o próximo elemento e pega o seu endereço de memória, logo assim, simplesmente podemos passar uma variável que não é ponteiro apenas informando o seu endereço de memória com o operador ¨¨& de referência. #include <stdio.h> #include <stdlib.h> char *string(char *ptr) { *ptr = 'b'; //colocar o b no endereço de memória do ptr return ptr; // retorna um ptr } int main(void) { char caracter = 'a'; printf("%c", caracter); string(&caracter); //pega o endereço de memória da variável caracter printf("%c", caracter); } 8-Utilizar-se ponteiros no código, pode garantir performance, e otimização com código genéricos, alocar memória dinamicamente, manipular endereços de memória, fazer callbacks, e um monte afim, além de ser mais visível achar erros. Segue um exemplo bem básico de ponteiro para função #include <stdio.h> #include <stdlib.h> int func(int a, int b) { return a + b; } int main(void) { int x = 5, y = 5; int (*ptr)(int x, int y); ptr = 0; printf("Ponteiro aponta para 0 : %p\n", ptr); ptr = func; printf("Ponteiro aponta para func: %p\nValor: %d", ptr, ptr(x,y)); } 9-O uso de ponteiros é bem extenso, no código abaixo vou deixar um exemplo de um array de ponteiros, de antemão, já digo que talvez não tenha explicado de maneira correta, pois simplifiquei, para ficar mais fácil o entendimento. Fiquei sem falar sobre alguns usos de ponteiros, tais como ponteiro para ponteiro, ponteiro para um array de um tipo de dado, entre outros, mas nestes casos, não vejo tanta usabilidade nos códigos. #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *ptr[] = {"Ponteiro", "is", "legal", NULL}; // Array de ponteiros puts(*ptr); // Exibe a string para onde o primeiro ponteiro aponta printf("%s\n%s\n", *(ptr+1), *(ptr+2)); // Exibe as strings avançado os bytes dos ponteiros putchar(ptr[0][5]); /* No primeiro [], informo q meu primeiro ponteiro aponta para a String Ponteiros, e ao usar [] novamente, informo para avançar 5 bytes da onde o primeiro ponteiro aponta, o resultado é a letra i*/ putchar('\n'); // Um array bidimensional é diferente de um array de ponteiros, internamente eles se comportam de maneira diferente na memória return 0; } Obs: Quando falam em performance ao usar ponteiros, quer dizer na verdade que são mais velozes, devido ao código que o compilador gcc gera, por isso logo vai ter menos ciclos e o processador vai executar mais rápido o programa. Bom, vou ficando por aqui, isso foi um resumo bem simples sobre ponteiros, fiquei na dúvida se postava ou não, porque sou bem noob em C, mas acredito que o fórum seja pra isso mesmo, compartilhar, independente do nível de conhecimento de cada um, espero que um dia eu fique bom nesse treco, haha. Agradecimentos ao Frederico e ao Mercês que me explicou sobre uso de ponteiros, lembrando, se tiver algum erro me avisem, ou se ficou ruim o texto desse jeito, seguido de código e mais código. Bye bye ao som de Vanessa Carlton - A thousand Miles
  2. O que vocês acham de ter mais um meio de comunicação para a galera do fórum?através do irc, raidcall, etc, seria bom para conversar em tempo real
  3. Um dos ambientes controlados já pronto e com interface intuitiva é o projeto bwapp, neste projeto você pode testar várias vulnerabilidades web e de servidor
×
×
  • Create New...