Aritmetica de ponteiro

Preciso criar uma função em c++ que recebe um vetor de inteiros(usando memoria dinamica), como parametro e inverta a ordem dos elementos, alterando o original que foi passado como argumento. O parâmetro formal da função que corresponde ao vetor que deve ser invertido tem que ser um ponteiro simples. Faça uma função em C++ chamada inverteVetor que recebe um vetor de inteiros (utilizando memória dinâmica) como parâmetro e inverte a ordem dos seus elementos, alterando o vetor original passado como argumento. O parâmetro formal da função correspondente ao vetor a ser invertido deve ser um ponteiro simples. O problema é que tenho que utilizar aritmética de ponteiros para percorrer o vetor, o prof não chegou a explicar e não consegui entender bem por conta.
No fim a função tem que ser implementada de um jeito que não precise usar um vetor auxiliar e nem percorrer todos os elementos do vetor original.
A função inverteVetor deve obedecer o seguinte protótipo:
void inverteVetor(int *piVet, const int tam);
onde piVet é o ponteiro para o vetor a ser invertido e tam é o tamanho do mesmo.

No fim, meu código ficou assim:
OBS: usei o New porque no final de tudo os vetores tem que ser deletados.

#include <iostream>
using namespace std;

void inverteVetor(int *piVet, const int tam);

int main(int argc, char const *argv[]) {
    int vet[] =  {1, 2, 3, 4, 5, 6, 7};
    
    for (int i = 0;  i < 7; i++) {
        cout << vet[i] << endl;
	}
   
	cout << "Vetor invertido: " << endl;
   	inverteVetor(vet, 7);

    for (int i = 0;  i < 7; i++) {
        cout << vet[i] << endl;
	}
	
	delete []vet;
}

void inverteVetor(int *p, const int tam) {
	int aux;
	int tamanho = tam-1;
    for (int i = 0; i < tam/2; i++){
    	aux = p[i];
    	p[i] = p[tamanho];
    	p[tamanho] = aux;
    	tamanho --;

	}

}

Funciona, mas não é para ser desse jeito. Alguém pode me ajudar e tentar me explicar? Tentei pedir ajuda para um colega que já pagou essa disciplina, mas ele me disse que nunca tinha usado isso e no fim não deu em nada.

vamos la

primeiro, remove esse delete do final. se vc não alocou com new, não use delete. em um sistema operacional de verdade isso ai da um belo erro.

segundo, aritmetica de ponteiro é vc fazer *(p + i ) ao invés de p[i]

isso funciona tanto para ler quanto para atribuir valores.

por isso se chama aritmetica: vc tem um ponteiro de um dado tipo e quando vc soma o endereço de memoria com um dado inteiro vc avança determinada quantidade de bytes. como um array é uma região contigua de memoria é facil pegar o elemento 5, por exemplo, pois ele esta a 5 * sizeof(int) de distancia do ponteiro para o primeiro elemento.

Como posso passar os valores como argumento usando o new? Sobre o delete também fiquei em dúvida, foi meu colega que disse que não teria problema. Vou ver o que fazer.

Só pra deixar mais claro e elaborar um pouco mais, o operador de subscrição [] é só um syntax sugar da linguagem para abstrair o uso dos ponteiros.

p[i] é convertido para (*((p) + (i))) em tempo de compilação. Por isso, inclusive, que essa sintaxe é válida:

int i = 1;
const char* p = "guj";
printf("%c", i[p]); // imprime "u"

Obrigado. Vou tentar aqui. Só mais uma coisa, como posso passar os valores como parâmetro usando o new? Não consigo acertar. Existe um jeito? Preciso usar o delete no final.

eu adoro perguntar coisas assim em entrevista:

#include<stdio.h>
int main(void){
  int x[]= {0,1,2};
  printf("%d - %d\n", x[1], 1[x]); /* o codigo compila? tem warning? o que seria impresso? */
  return 0;
}

Você ainda está na Weborama?

Desculpa me meter na conversa de vocês, mas será que alguém pode responder minha pergunta sobre o “New”?

vamos la

new vai alocar um objeto na Heap. isso vai existir até que vc use delete. por isso o mantra: para cada new, um delete.

se vc não deleta vc alocou memora e não desalocou. dependendo do programa vc pode consumir a memoria toda e vai dar ruim.

depende do ciclo de vida que vc quer: se vc criou um array ( ou qq objeto ) e vai usa-lo dentro daquele bloco lexico, então vc provavelmente não precisa de new, vc poderia criar na stack pois no fim do bloco lexico tudo ali sera apagado.

{

  int variavel[] = {1,2,3};
  ...
  algumaFunção(variavel, ... )
  ...
} 

a algumaFunção vai fazer algo com a variavel e acabou. é diferente de

*int meDaUmArrayDe10elementos(){
  var *variavel = new int[10];
  return variavel;
}

aqui a variavel precisa continuar existindo ao fim desse bloco lexico. então quem chamar essa função vai ter q fazer um delete manual.

uma vez que vc sacou os usos de cada um e leu isso:

vc ainda tem duvidas? se sim, quais?

Eu to usando o dev-C++.
Consegui fazer a função para inverter usando a aritmética, e quando eu compilo aparece isso:
[Warning] deleting array ‘vet’ [enabled by default]
Aparecendo isso não quer dizer o deletou o array mesmo sem o new? Ou é por causa do compilador?

Ou isso é um alerta de erro mesmo? Me foi dito antes que isso era só um aviso e queria dizer que tava deletando mas agora eu to na dúvida.

vc não deve deletar algo q vc não iniciou com new.

delete exige new

assim como free exige malloc ( ou outras funções)

Obrigado. Vou tentar arrumar aqui.

uma melhor explicação esta aqui:

http://www.cplusplus.com/doc/tutorial/dynamic/

e C++ hoje me dia tem suporte a smart pointers. que no fim das contas ajudam pra caramba

Ainda não entendo essa coisa de alocação de memória, mas tenho que arrumar meu código para rodar usando isso. Vou ler o que me mandou.

É bem simples: Pense em espaço físico. Pra algo físico existir, ele deve ocupar um espaço físico, certo? Por exemplo, para um mouse existir, ele deve ocupar um espaço.

Então, isso é alocação de memória. Pra algo existir no heap, ele precisa alocar um espaço. Só que o heap é limitado, não vai crescendo. Se você for criando coisas e não “desocupando lugar para novas”, você terá problemas.

:wink:

1 curtida