vetor como argumento de função [RESOLVIDO]

1. vetor como argumento de função [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 11/10/2022 - 10:37h

olá
alguem sabe me dizer a diferença dos argumentos:

qualquercoisa(int *vetor) {}
qualquercoisa(int* vetor) {}
qualquercoisa(int vetor[]) {}


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 12/10/2022 - 03:19h

Os três são absolutamente sinônimos.

De cara, “int *vetor” e “int* vetor” são exatamente a mesma coisa do ponto de vista sintático, mudando apenas a forma de usar espaços; seria a mesma se a pessoa fizesse “int*vetor” ou “int * vetor”.

Já a forma “int vetor[]” é ligeiramente diferente porque, embora nesse caso ela seja sinônima das apresentadas acima, esta forma só pode ser usada na declaração de parâmetros de funções, não podendo ser usada em outras declarações do C++, tais como variáveis ou campos de estruturas ou classes. Essa forma sintática é, ao mesmo tempo, uma reminiscência da linguagem B (ancestral do C, que é ancestral do C++), que usava essa mesma sintaxe para seus ponteiros e não possuía a notação com asteriscos, e também uma decorrência do fato que, na maioria dos contextos, o uso de um array como parte de uma expressão provoca o aparecimento de um valor que é meramente um ponteiro para o primeiro elemento de tal array. Esse segundo ponto, inclusive, faz com que sejam sinônimas também a forma que use um valor inteiro entre os colchetes (por exemplo, algo como “int vetor[50]”), porque quando tal forma é usada na declaração de um parâmetro de função, ali não se está provocando a alocação de memória, mas preparando a função para receber o endereço inicial de um bloco de memória que foi alocado em algum outro lugar, de modo que apenas um endereço é passado à função, em vez de todos os elementos do array.

Já vi em alguns contextos se advogar o uso de “int vec[]” (ou mesmo “int vec[n]”, sendo n um valor inteiro positivo) em lugar de “int *vec” como parâmetro da função sempre que for esperado que o argumento passado à função seja um array, e não um ponteiro genérico, que poderia se referir a apenas um valor inteiro ou mesmo ser um ponteiro nulo ou inválido. Entretanto, esse uso é meramente uma convenção, não alterando de modo nenhum o comportamento da linguagem, que continua tratando tais parâmetros como meros ponteiros. É por isso, por exemplo, que você vê, por exemplo, as duas formas abaixo sendo usadas na declaração da função main, embora ambas tenham o sentido de, no segundo argumento, receber um ponteiro para ponteiro para caracteres, o qual é usado para receber um vetor de tamanho não predeterminado de ponteiros para caracteres.
int main(int argc, char *argv[]) 
int main(int argc, char **argv) 


Eu particularmente não sigo essa convenção (por exemplo, das duas forma acima, eu geralmente uso a segunda), e o faço justamente porque, além de digitar um caráter a menos, no fim das contas, o argumento será um ponteiro e o parâmetro é um ponteiro, não vetores. Creio que isso é bem ilustrado pelo código abaixo.
#include <iostream>

int vglobal[50];

void f(int vparam[50]){
std::cout << "Tamanho: " << sizeof vparam << "\tEndereço 1º elemento: " << vparam << "\tEndereço da variável: " << &vparam << '\n';
}

int main(void){
int vlocal[50];
std::cout << "Tamanho: " << sizeof vglobal << "\tEndereço 1º elemento: " << vglobal << "\tEndereço da variável: " << &vglobal << '\n';
std::cout << "Tamanho: " << sizeof vlocal << "\tEndereço 1º elemento: " << vlocal << "\tEndereço da variável: " << &vlocal << "\n\n";
f(vglobal);
f(vlocal);
}

De cara, ao compilar tal código, vem uma mensagem de alerta.
x.cc: In function ‘void f(int*)’:
x.cc:6:40: warning: ‘sizeof’ on array function parameter ‘vparam’ will return size of ‘int*’ [-Wsizeof-array-argument]
6 | std::cout << "Tamanho: " << sizeof vparam << "\tEndereço 1º elemento: " << vparam << "\tEndereço da variável: " << &vparam << '\n';
| ^~~~~~
x.cc:5:12: note: declared here
5 | void f(int vparam[50]){
| ~~~~^~~~~~~~~~

E, de fato, a saída do programa executado mostra essa diferença. Note como, nas duas primeiras linhas, os endereços dos respectivos primeiros elementos são numericamente equivalentes aos endereços dos arrays como um todo (i.e. o primeiro dos 200 bytes que compõem cada um deles, com 4 bytes por elemento, portanto), e como, nas duas últimas, o tamanho do suposto array não tem nada a ver com a quantidade suposta de 50 elementos nem com o tamanho de cada elemento (4 bytes), mas sim o tamanho de um ponteiro, e como o endereço do primeiro elemento não coincide com o endereço do suposto array, mas que é, na verdade, o endereço onde reside o ponteiro recebido como parâmetro.
Tamanho: 200    Endereço 1º elemento: 0x563300222160    Endereço da variável: 0x563300222160
Tamanho: 200 Endereço 1º elemento: 0x7ffe6fae0820 Endereço da variável: 0x7ffe6fae0820

Tamanho: 8 Endereço 1º elemento: 0x563300222160 Endereço da variável: 0x7ffe6fae0808
Tamanho: 8 Endereço 1º elemento: 0x7ffe6fae0820 Endereço da variável: 0x7ffe6fae0808


Para ter arrays de tamanho fixo como argumentos de funções, há três abordagens que me ocorrem agora (certamente entre outras possíveis).

A primeira é usar referências (C++) ou ponteiros (C e C++) para os arrays como parâmetros das funções.
// Tradicional: indicação de array é mera convenção; o que se tem é ponteiro para primeiro elemento.
void func1(int vec[50]){ /* bla bla bla */ }

// Ponteiro para array: válida em C e C++.
void func2(int (*pvec)[50]){ /* bla bla bla */ }

// Referência para array (somente C++).
void func3(int (&rvec)[50]){ /* bla bla bla */ }


int main(void){
int v50[50], v30[30];

func1(v50); // OK.
func2(&v50); // OK. Note que foi necessário usar o “&”.
func3(v50); // OK, mas note que visualmente não é distinguível de func1, embora seja funcionalmente bem diferente.

func1(v30); // Sintaticamente OK, porém possivelmente problemático se a função tentar mexer do 31º elemento em diante.
func2(&v30); // ERRO: tipo de ponteiro incompatível.
func3(v30); // ERRO: tipo incompatível.

int *p;

p=v50;
func1(p); // OK (sintaticamente e logicamente).
func2(&p); // ERRO: tipo de ponteiro incompatível
func3(p); // ERRO: tipo incompatível.

p=v30;
func1(p); // Sintaticamente OK, porém possivelmente problemático se a função tentar mexer do 31º elemento em diante.
func2(&p); // ERRO: tipo de ponteiro incompatível
func3(p); // ERRO: tipo incompatível.

func1(nullptr); // Sintaticamente OK. Logicamente, se a função tiver tratamento de ponteiro nulo, pode fazer sentido; caso contrário, pode dar problema.
func2(nullptr); // Sintaticamente OK. Logicamente, se a função tiver tratamento de ponteiro nulo, pode fazer sentido; caso contrário, pode dar problema.
func3(*(p=nullptr)); // Sintaticamente OK, mas certamente vai dar SIGSEGV em tempo de execução.
}


A segunda abordagem seria substituir o uso de array nativos por std::array, no caso de funções cujos argumentos tenham de ter tamanho fixo, ou por std::vector, caso tenham de ser arrays de tamanho não previamente conhecido ou que possa variar dinamicamente. Dependendo das operações, pode necessário passar objetos dessas classes por referência.

A terceira é possivelmente uma forma ancestral da segunda: encapsular um array dentro de uma estrutura ou união contendo apenas tal array.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)

3. RE: vetor como argumento de função

Luiz Eduardo Maia Ribeiro
distromaialinux

(usa Debian)

Enviado em 11/10/2022 - 11:14h


qualquercoisa(int *vetor) {} = parâmetro de variável do tipo inteira que aponta para endereço de memória
qualquercoisa(int* vetor) {} = parâmetro de variável do tipo inteira que aponta para endereço de memória mas acho que assim daria errado
qualquercoisa(int vetor[]) {} = parâmetro de variável do tipo vetor ou lista de valores inteiros


4. Re: vetor como argumento de função

Perfil removido
removido

(usa Nenhuma)

Enviado em 11/10/2022 - 11:40h

mas porque os 3 fazem a mesma coisa aqui ?

void imprimeVetor(int tamanho, int *vetor)
for(int i=0;i<tamanho;i++)
cout << '\t' << vetor[i] << endl;

void imprimeVetor(int tamanho, int* vetor)
for(int i=0;i<tamanho;i++)
cout << '\t' << vetor[i] << endl;

void imprimeVetor(int tamanho, int vetor[])
for(int i=0;i<tamanho;i++)
cout << '\t' << vetor[i] << endl;


5. Re: vetor como argumento de função [RESOLVIDO]

Samuel Leonardo
SamL

(usa XUbuntu)

Enviado em 12/10/2022 - 09:46h

Paulo como sempre arrasa nas respostas. Excelente!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts