Leandro Fróes Posted February 15, 2018 at 04:46 PM Share Posted February 15, 2018 at 04:46 PM Boa tarde galera, um tempo atrás fiquei com uma dúvida e tanto sobre ponteiros, principalmente com um uso em específico. Tendo isso em mente decidi jogar aqui pra vocês testarem e pensarem, acho que vai ser legal pra geral aprender. P.S Não usem o google, testem - Qual a diferença entre (*p) e *p? Só será validada a resposta daquele que mostrar o código e o pq, sem compromisso galera, apenas pra descontrair Abraços! Link to comment Share on other sites More sharing options...
kassane Posted February 17, 2018 at 03:09 PM Share Posted February 17, 2018 at 03:09 PM *p = valor da posição de memoria; (*p) = valor da posição da posição de memória neste caso usando um array/vetor void f() { int v[] = {1, 2, 3}, x=24; int * p= NULL; p = &x; std::cout << *p << "!\n"; //output o valor de x = 24 std::cout << (*v)+1 << "!\n"; //output 2 } PS: Caso eu tenha dito besteira favor me corrija! Link to comment Share on other sites More sharing options...
Leandro Fróes Posted February 17, 2018 at 04:30 PM Author Share Posted February 17, 2018 at 04:30 PM 1 hora atrás, kassane disse: *p = valor da posição de memoria; (*p) = valor da posição da posição de memória neste caso usando um array/vetor void f() { int v[] = {1, 2, 3}, x=24; int * p= NULL; p = &x; std::cout << *p << "!\n"; //output o valor de x = 24 std::cout << (*v)+1 << "!\n"; //output 2 } PS: Caso eu tenha dito besteira favor me corrija! Opa, na verdade *p aponta para o conteúdo do endereço que tem dentro de p, como ai foi um vetor ele aponta para o endereço do primeiro elemento do vetor. Se você fizer (*v)+1 ele vai pegar o primeiro elemento e somar 1 e não andar uma posição. Ai deu certo porque 1+1 da 2 . Exemplo: #include <stdio.h> int main(){ int v[] = {10,20,30}; int *p = v; printf("Segunda posicao do vetor: %d\n", (*p)+2); return 0; } user@user:/home# ./test Segunda posicao do vetor: 12 Mas o caminho pra achar a resposta é esse mesmo: arrays. Vou esperar mais um tempo antes de postar a resposta. Abraço! Link to comment Share on other sites More sharing options...
Leandro Fróes Posted February 25, 2018 at 04:40 AM Author Share Posted February 25, 2018 at 04:40 AM Queria deixar uma pergunta interessante para se pensar antes de resolver o desafio. Considerando o ponteiro p: O que acontece se usarmos p++? E quando se usa (*p)++? Tente aplicar em um array e veja seus elementos =D Abraço! Link to comment Share on other sites More sharing options...
Pimptech Posted February 25, 2018 at 07:42 AM Share Posted February 25, 2018 at 07:42 AM Falai, Leandro! Bele ? Legal essa questão, trabalhar com pointeiro é tenso. Nada melhor que treinar ;p Nesse caso, se printarmos o "p++" direito no printf o valor não irá mudar. Pois o operador ++ usado após a variável só incrementado depois de valor de p ser mostrado no print. Ou seja, no print ele n muda. Porém se você usar o operador antes da variável ++p ele primeiro soma o valor de p para então usá-lo. No caso de p++ ele irá acrescentar o tamanho do ponteiro p. Se for int em 32bit endereço de p + 4. No caso do (*p)++ é o mesmo lance do operador, mas nesse caso ele soma o valor contido no primeiro elemento do array. Vale ressaltar que o parentes são opcionais, não muda em nada. Abraço! ;]] Link to comment Share on other sites More sharing options...
gzn Posted February 25, 2018 at 01:31 PM Share Posted February 25, 2018 at 01:31 PM #include <stdio.h> int main(void){ int a[] = {10,20}; int *p = a; // De primeira a gente acha que a ordem de interpretação dos parâmetros é da // esquerda para direita, mas não. // 2º 1º a ser interpretado printf("*(++p): %d\t++(*p): %d\n", *(++p), ++(*p)); //volta o valor original de p (endereço de a) p--; // 2º 1º (p agora é a[1] que é 20) printf("++(*p): %d\t*(++p): %d\n", ++(*p), *(++p)); return 0; } Saída: *(++p): 20 ++(*p): 11 ++(*p): 21 *(++p): 20 Se eu escrevi alguma bobeira por favor me corrijam rs Explicando melhor! Se no primeiro printf o primeiro parâmetro (da esquerda para direita) fosse avaliado primeiro teríamos que ter 20 e 21, não 20 e 11. O que parece acontecer é: Pega-se o valor de *p e soma 1 (isso da 11) e guarda esse valor (2º parâmetro da esquerda para direita) Incrementa-se o valor do endereço de p e pega seu valor (isso dá 20) (1º parâmetro da esquerda para direita) A impressão desses valores segue a ordem "normal" da esquerda para direita, aí dá 20 e 11. Fiz isso para mostrar a diferença nos usos do parêntesis e também o que acontece quando passamos parâmetros para funções (melhor dizendo, como elas são avaliadas, em que ordem). Link to comment Share on other sites More sharing options...
Pimptech Posted February 25, 2018 at 05:22 PM Share Posted February 25, 2018 at 05:22 PM 3 horas atrás, gzn disse: #include <stdio.h> int main(void){ int a[] = {10,20}; int *p = a; // De primeira a gente acha que a ordem de interpretação dos parâmetros é da // esquerda para direita, mas não. // 2º 1º a ser interpretado printf("*(++p): %d\t++(*p): %d\n", *(++p), ++(*p)); //volta o valor original de p (endereço de a) p--; // 2º 1º (p agora é a[1] que é 20) printf("++(*p): %d\t*(++p): %d\n", ++(*p), *(++p)); return 0; } Saída: *(++p): 20 ++(*p): 11 ++(*p): 21 *(++p): 20 Se eu escrevi alguma bobeira por favor me corrijam rs Explicando melhor! Se no primeiro printf o primeiro parâmetro (da esquerda para direita) fosse avaliado primeiro teríamos que ter 20 e 21, não 20 e 11. O que parece acontecer é: Pega-se o valor de *p e soma 1 (isso da 11) e guarda esse valor (2º parâmetro da esquerda para direita) Incrementa-se o valor do endereço de p e pega seu valor (isso dá 20) (1º parâmetro da esquerda para direita) A impressão desses valores segue a ordem "normal" da esquerda para direita, aí dá 20 e 11. Fiz isso para mostrar a diferença nos usos do parêntesis e também o que acontece quando passamos parâmetros para funções (melhor dizendo, como elas são avaliadas, em que ordem). Falai, @gzn. Bele ? Bacana o exemplo! =) Porém só queria acrescentar que os parenteses não fazem diferença. Se você remove-los o resultado será o mesmo. O que importa é a ordem de incremento. Se incrementar diretamente o ponteiro ++p, o endereço será incrementado no tamanho do ponteiro. Então podemos usar *++p para incrementar primeiro o endereço(ponteiro) e depois "castar" para pegar o valor que o endereço de p aponta. Parenteses em ponteiros são ilustrativos, dão uma sensação de separação, são usados mais para deixar o código mais "legível". É nois! Abraço! Link to comment Share on other sites More sharing options...
gzn Posted February 25, 2018 at 05:45 PM Share Posted February 25, 2018 at 05:45 PM Sr. @Pimptech obrigado pelos esclarecimentos. E ai @Leandro Fróes , vc tem algum comentário para ajudar a gente a entender melhor isso? comenta aí! rs Se o @fredericopissarra puder vir aqui e dar um comentário extra também seria uma boa, pq esse sr. entende bastante (esses dias quando fiz o curso do merces de prog moderna em c li muitos comentários dele lá) Link to comment Share on other sites More sharing options...
Felipe.Silva Posted February 27, 2018 at 12:27 AM Share Posted February 27, 2018 at 12:27 AM Bom, a diferença entre *p e (*p), puramente, é nenhuma. Agora, você falou sobre usar incrementos... Ai sim os parênteses fazem diferença... Já que se nós escrevemos *p++ irá resultar em: 1) É usado o valor que p está apontando no momento. 2) DEPOIS da operação é incrementado o valor do ponteiro p. Agora, ao fazer (*p)++ o resultado é: 1) É usado o valor que p está apontando. 2) DEPOIS da operação é incrementado o valor ONDE o ponteiro aponta... Isto é, sem os parênteses é incrementado o endereço para onde p aponta. E com os parênteses é incrementado o VALOR que p está apontando na memória. Como você pediu, deixo um código exemplificando:https://ghostbin.com/paste/8gpjw Link to comment Share on other sites More sharing options...
gzn Posted February 27, 2018 at 01:14 AM Share Posted February 27, 2018 at 01:14 AM 1 /** 2 * Hehe, esse negócio confunde mesmo. 3 * O parenteses parece fazer diferença conforme o uso. 4 */ 5 #include <stdio.h> 6 int main(void){ 7 int a[] = {10, 20}, *p = a; 8 9 (*p)++; 10 printf("%d\n", *p); // saída é 11 11 12 *p++; 13 printf("%d\n", *p); // saída é 20 14 15 return 0; 16 } E aí, faz ou não faz diferença? Link to comment Share on other sites More sharing options...
Pimptech Posted February 27, 2018 at 04:07 PM Share Posted February 27, 2018 at 04:07 PM 14 horas atrás, gzn disse: 1 /** 2 * Hehe, esse negócio confunde mesmo. 3 * O parenteses parece fazer diferença conforme o uso. 4 */ 5 #include <stdio.h> 6 int main(void){ 7 int a[] = {10, 20}, *p = a; 8 9 (*p)++; 10 printf("%d\n", *p); // saída é 11 11 12 *p++; 13 printf("%d\n", *p); // saída é 20 14 15 return 0; 16 } E aí, faz ou não faz diferença? É, faz hehe.. Se quiser isolar primeiro o valor que p aponta e depois usar o incremento. Caso específico. Muito bom, n tinha pensado nesse ponto. Vivendo e aprendo Link to comment Share on other sites More sharing options...
Leandro Fróes Posted March 3, 2018 at 03:30 PM Author Share Posted March 3, 2018 at 03:30 PM Boa tarde pessoal! Muito foda que vocês tentaram, deixaram o post muito completo. Bom, mas eai? Qual a diferença? Depende kkkkkkk Até onde eu sei (e se alguém souber mais por favor, compartilhe) o parênteses serve para dar ênfase. Na prática eu vejo algumas situações que fazem diferença e duas já foram citadas aqui. São elas: Incremento (ou decremento): aqui *p++ anda de acordo com o tipo de dado que o ponteiro aponta e (*p)++ da ênfase ao elemento apontado. Percorrendo um array: #include <stdio.h> int main(){ int v[] = {10,20,30}; int *p = v; int i; for(i=0;i<3;i++){ printf("Com parenteses: %d\n", *(p+i)); printf("Sem parenteses: %d\n", *p+i); } } Saída: Com parenteses: 10 Sem parenteses: 10 Com parenteses: 20 Sem parenteses: 11 Com parenteses: 30 Sem parenteses: 12 E um outro caso que não foi comentado aqui é para declaração de arrays. Quando usamos int *v[] estamos criando um array de ponteiros do tipo intero. Agora quando usamos int (*v)[] estamos criando um ponteiro para um array de inteiros. Mas é isso ai galera, desafio concluído e já achamos 3 coisas interessantes, alguém tem algo mais para mostrar para nós? Abraços!! Link to comment Share on other sites More sharing options...
fredericopissarra Posted March 8, 2018 at 12:34 AM Share Posted March 8, 2018 at 12:34 AM Meus dois dedinhos de prosa, se é que já não explicaram isso exaustivamente ai em cima... "Ponteiro" é apenas uma variável, como qualquer outra, que contém um ENDEREÇO de memória ao invés de um valor do tipo especificado. Existe diferença entre a DECLARAÇÃO de algo e seu USO, especialmente quando se lida com "ponteiros". Abaixo, temos uma declaração de uma variável p que é um ponteiro que aponta para um char, na memória. Obviamente a variável não está inicializada (assim como você pode fazer com declarações como "int x;"): char *p; E, abaixo, temos a declaração de um array s contendo uma string e a inicialização do ponteiro p que passa a apontar para o 3º byte da string: char s[] = "Fred"; char *p; p = &s[2]; // & é o OPERADOR "endereço de"... Assim como com outros tipos de variáveis, OPERAÇÕES são efetuadas usando OPERADORES como +, -, *, /, =, etc. Só que, com ponteiros, o símbolo * é também usado como OPERADOR DE INDIREÇÃO, ou seja, ele pega o endereço no interior da variável e usa para localizar o dado referenciado por esse endereço. Quando fazemos: *p = 'a'; // usando o ponteiro inicializado acima A variável p (ponteiro p) contém o endereço (aponta para) do 3º item do array s. O * antes de p é o OPERADOR DE INDIREÇÃO que usa o endereço contido em p e pega (ou escreve, neste caso, porque temos o operador = e a expressão está do lado esquerdo) o caracter apontado. A expressão *p pega/escreve 1 caracter porque este é o tipo APONTADO pela variável p. Quando usamos operadores como +, -, ++ e -- com ponteiros trabalhamos com aritmética (duh!), mas o endereço será incrementado ou decrementado de acordo com o tamanho do tipo... Por exemplo, se fizermos: int x[] = { 1, 2, 3, 4}; int *p = &x[1]; printf("%d\n", *++p); Assumindo que p tem um endereço 0x400020 depois de inicializado, ao fazer ++p ele conterá 0x400024, ou seja, incrementamos o endereço em 4 unidades porque o tamanho de um "int" é de 4 bytes. mas note que a expressão que usei no printf() foi *++p. Isso quer dizer que fazemos um pré-incremento de p (p apontará para a posição do array x que contém o 3) e depois usamos o operador de indireção para ler o valor 3 no endereço dado por p. Neste ponto podemos responder qual é a diferença entre *p e (*p)... NENHUMA! Note que se tivéssemos uma expressão como: a = b; Faz alguma diferença se escrevessemos isso como "a = (b)"? Os parênteses ai é um operador, mas é usado apenas para forçar a ordem de precedência da expressão como um todo. Isso não significa que parensteses não possam ser usados para DECLARAR tipos diferentes de ponteiros... Por exemplo: int *a[]; // a é um array de ponteiros para int. int (*a)[]; // a é um ponteiro de arrays para int. E, às vezes, os parenteses ajudam a garantir que uma expressão faça o que queremos que ela faça... Por exemplo: c = *p++; // mesma coisa que c=*p; p=p+1; c = (*p)++; // mesma coisa que c = *p; t = *p; t = t + 1; *p = t; Aliás... não é obvio, mas ao obtermos um N-ésino item de um array a, por exemplo, via a[N], na verdade o símbolo 'a' é o ponteiro para o primeiro elemento do array que é somado ao valor N e depois "derreferenciado" (via um operador de indireção implícito)... Ou seja: a[N] == *(a + N) Isso gera um "macete" interessante, mas perigoso: a[N] também pode ser escrito como N[a] (tente, o compilador não reclamará!). Isso porque *(a + N) é a mesma coisa que *(N + a) - propriedade comutativa da adição! Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.