Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Patrícia Silva

Parâmetros de função por referência e Matrizes

Recommended Posts

Pessoal,

 

estou tentando fazer um programa que receba uma matriz bidimensional e a modifique numa função que possui parâmetros por referência. A título de teste, no exemplo abaixo eu usei apenas uma posição da matriz ([0][0]), mas se funcionar para esse campo, funcionará para todos os demais.

 

Pois bem: quando eu compilo o programa, ele retorna a seguinte mensagem de erro: expected expression before ´]´ token.

 

Preciso da ajuda de alguém para descobrir como corrigir esse erro... :(

 

 

#include <stdio.h>
#include <stdlib.h>

void GerarMatrizFinal(int *teste[][2])
{
   double numero = 5.00;
   numero = (double)*teste[0][0] + numero;
   printf("%f\n", numero);
}

int main()
{
   int cont[2][2];
   GerarMatrizFinal(&cont[2][]);
   return 0;
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pessoal,

 

estou tentando fazer um programa que receba uma matriz bidimensional e a modifique numa função que possui parâmetros por referência. A título de teste, no exemplo abaixo eu usei apenas uma posição da matriz ([0][0]), mas se funcionar para esse campo, funcionará para todos os demais.

 

Pois bem: quando eu compilo o programa, ele retorna a seguinte mensagem de erro: expected expression before ´]´ token.

 

Preciso da ajuda de alguém para descobrir como corrigir esse erro... :(

 

 

#include <stdio.h>

#include <stdlib.h>

 

void GerarMatrizFinal(int *teste[][2])

{

double numero = 5.00;

numero = (double)*teste[0][0] + numero;

printf("%f\n", numero);

}

 

int main()

{

int cont[2][2];

GerarMatrizFinal(&cont[2][]);

return 0;

}

 

Patrícia,

 

Para passar uma matriz por referencia é necessário utilizar ponteiro para ponteiro, e alocar a matriz dinamicamente.

 

O código abaixo esta compilavel no code::Blocks.

#include <stdio.h>
#include <stdlib.h>

void GerarMatrizFinal(int **teste)
{

   int i = 0;
   int j = 0;

   teste[i][j] = 5;

   double numero = 0;
   numero = teste[i][j];
   printf("%f\n", numero);
}

int main()
{
   int cont[2][2];
   int **Matriz_dinamica = new int*[2];
   for(int i = 0;i < 2;i++)
       Matriz_dinamica[i] = new int[2];

   GerarMatrizFinal(Matriz_dinamica);
   return 0;
}

 

 

Espero ter ajudado.

 

Sds, Gabriel Becker

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não existe passagem de argumentos por referência em C. Existem diferenças importantes entre ponteiros e a noção de referência que se tem em linguagens como Java (pra não falar em C++, que não conheço).

 

O código acima é C++.

 

No programa original, observe o seguinte protótipo:

 

void GerarMatrizFinal(int *teste[][2]);

 

Acima, 'teste' tem tipo 'vetor de 2 vetores de ponteiros para int'. Como em C só existe passagem de argumento por valor, e o valor de qualquer vetor é um ponteiro para seu primeiro elemento, o tipo efetivo de 'teste' é 'ponteiro para vetor de 2 ponteiros para int'.

 

Para manipular vetores de vetores de int, você só precisa de um ponteiro para um vetor de ints:

 

#include <stdlib.h>

#define N 15

void set(int (*linha)[N], size_t n_linhas, int valor)
{
   size_t i, j;

   for (i = 0; i < n_linhas; i++)
   {
       for (j = 0; j < N; j++)
       {
           linha[i][j] = valor;
       }
   }
}

int main(void)
{
   int matriz[N][N] = { { 0 } }; // corrigido o erro observado abaixo

   set(matriz, N, 100);

   return 0;
}

 

Note que (novamente, por causa da regra sobre o valor de vetores) as seguintes declarações são equivalentes:

 

void set(int linha[][N], size_t n_linhas, int valor);
void set(int (*linha)[N], size_t n_linhas, int valor);

Compartilhar este post


Link para o post
Compartilhar em outros sites

Guidjos,

 

Vou ter que descordar com você. Existe sim passagem de parâmetro por referencia em C. Com o uso de ponteiros, onde se passa o endereço da variável. Ou seja, a referencia para a variável.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Patrícia,

 

Para passar uma matriz por referencia é necessário utilizar ponteiro para ponteiro, e alocar a matriz dinamicamente.

 

O código abaixo esta compilavel no code::Blocks.

#include <stdio.h>
#include <stdlib.h>

void GerarMatrizFinal(int **teste)
{

   int i = 0;
   int j = 0;

   teste[i][j] = 5;

   double numero = 0;
   numero = teste[i][j];
   printf("%f\n", numero);
}

int main()
{
   int cont[2][2];
   int **Matriz_dinamica = new int*[2];
   for(int i = 0;i < 2;i++)
       Matriz_dinamica[i] = new int[2];

   GerarMatrizFinal(Matriz_dinamica);
   return 0;
}

 

 

Espero ter ajudado.

 

Sds, Gabriel Becker

 

Gabriel, primeiramente obrigada pela ajuda.

Então... tentei compilar seu código (também no codeblocks), mas ele deu erro nas linhas 20, 21 e 23. Um dos erros foi:

 

Linha 21: erro: FOR loop initial declarations are only allowed in C99 mode.

 

Peço desculpas por não ter especificado a vocês, mas estou programando na versão 10 do codeblocks, no ubuntu.Talvez seu código não tenha rodado no meu codeblocks por uma questão de configuração mesmo.

Além disso, peço que não respondam em C++, porque não conheço a linguagem.

 

Não existe passagem de argumentos por referência em C. Existem diferenças importantes entre ponteiros e a noção de referência que se tem em linguagens como Java (pra não falar em C++, que não conheço).

 

O código acima é C++.

 

No programa original, observe o seguinte protótipo:

 

void GerarMatrizFinal(int *teste[][2]);

 

Acima, 'teste' tem tipo 'vetor de 2 vetores de ponteiros para int'. Como em C só existe passagem de argumento por valor, e o valor de qualquer vetor é um ponteiro para seu primeiro elemento, o tipo efetivo de 'teste' é 'ponteiro para vetor de 2 ponteiros para int'.

 

Para manipular vetores de vetores de int, você só precisa de um ponteiro para um vetor de ints:

 

#include <stdlib.h>
#include <stdio.h>

#define N 15

void set(int (*linha)[N], size_t n_linhas, int valor)
{
   size_t i, j;

   for (i = 0; i < n_linhas; i++)
   {
       for (j = 0; j < N; j++)
       {
           linha[i][j] = valor;
       }
   }
}

int main(void)
{
   int matriz[N][N] = { 0 };

   set(matriz, N, 100);

   return 0;
}

 

Note que (novamente, por causa da regra sobre o valor de vetores) as seguintes declarações são equivalentes:

 

void set(int linha[][N], size_t n_linhas, int valor);
void set(int (*linha)[N], size_t n_linhas, int valor);

 

Guidjos, obrigada. Mas seu código também deu erro no meu compilador, rs. Na inicialização da matriz (linha 21):

* missing braces around initializer;

* (near initialization for ´matriz[0]´)

 

Eu entendi mais ou menos o que você disse (mais pra menos que pra mais, rs). Achei confuso essa coisa de "vetor de 2 vetores de ponteiros para int", ou "ponteiro para vetor de 2 ponteiros para int". Você pode explicar melhor?

 

Outra dúvida: eu vi que no meu código eu declarei *linha[N] (tá, tinha um colchete a mais, mas estou frisando o fato de 'asterisco-linha' estar fora de parênteses) e você declarou como (*linha)[N]. Existe diferença?

 

[]'s

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mals por ter passado o código em C++. Patrícia.

Quanto ao post do guidjos. Vou tentar explicar o que eu entendi.

Imagina três vetores, dois vetores tem valores int, e o terceiro contém nas duas posições ponteiros para os dois vetores com valores int.

Foi isso que eu entendi.

Se estiver errado me corrija guidjos.

 

Tenho o ubuntu também, vou tentar compilar nele.

 

Flw!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Patrícia: realmente houve um engano. Ao invés de {0}, eu deveria ter escrito {{0}}. Desculpe. Segue o código com a correção:

 

#include <stdlib.h>

#define N 15

void set(int (*linha)[N], size_t n_linhas, int valor)
{
   size_t i, j;

   for (i = 0; i < n_linhas; i++)
   {
       for (j = 0; j < N; j++)
       {
           linha[i][j] = valor;
       }
   }
}

int main(void)
{
   int matriz[N][N] = { { 0 } };

   set(matriz, N, 100);
   return 0;
}

 

Para compilar o código acima:

 

gcc -std=c99 -Wall -Wextra -pedantic -Werror [arquivo.c] -o [arquivo]

 

Sobre a diferença dos parênteses nas declarações:

 

int *v[5];  // vetor de 5 ponteiros para int
int (*p)[5] // ponteiro para vetor de 5 ints

 

Acima, (v + 1) aponta para sizeof (int *) bytes depois do valor de v (lembre-se: o valor de um vetor é sempre um ponteiro para seu primeiro elemento). Contudo, (p + 1) aponta para sizeof (int[5]) bytes depois do valor de p.

Não deixe de notar que v é um vetor, e p, um ponteiro. Talvez este material a ajude a entender esses conceitos: http://guipn.com/cpa.htm .

 

 

GBecker: um vetor de vetores de ponteiros para int é como outro vetor qualquer. Cada um de seus elementos é em si um vetor, e cada elemento de cada um destes vetores é um (int *).

Compartilhar este post


Link para o post
Compartilhar em outros sites

GBecker: um vetor de vetores de ponteiros para int é como outro vetor qualquer. Cada um de seus elementos é em si um vetor, e cada elemento de cada um destes vetores é um (int *).

 

Ok guidjos.

 

Mas matriz na memória não seria assim?

Uma matriz na memória é um conjunto de vetores. Tem um vetor de tamanho[nº de linhas da matriz], e este vetor tem em suas posições ponteiros para outros vetores que são as linhas da matriz.

 

Meu conceito está errado??

 

Vlw!

 

Sds, Gabriel Becker.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ok, mas como seria a matriz? A nível de memória??

Compartilhar este post


Link para o post
Compartilhar em outros sites

Este é o núcleo da questão. Em C, não existem 'matrizes'. Geralmente representamos matrizes como vetores de vetores. Assim:

 

int a[2][3];

 

Acima, declarei um vetor de 2 vetores de 3 ints. Os elementos deste vetor são a[0] e a[1], e cada um deles é, em si, um vetor de 3 ints, ou int[3]. a[0][1] é o segundo elemento do vetor a[1]. Ou seja, é o segundo elemento do primeiro elemento do vetor a. Note que a[x][y] é o mesmo que *(*(a + x) + y).

 

Em memória, a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], ..., a[2][2] são dispostos de forma adjacente. Contudo, é errado usar a expressão a[0][4] para acessar o segundo elemento do segundo elemento de a (a[1][1]), porque apesar de, em termos de endereçamento e alinhamento eles designarem o mesmo objeto, acessar elementos fora do limite de um vetor gera undefined behavior. Na verdade, nem seria preciso a[0][4] para isto: a[0] + 4 já seria suficiente, pois há outra regra dizendo que UB é gerado ao tomar o endereço do elemento 'mais-que-um' após o último elemento de um vetor. Em ambos os casos, as violações se dão em relação ao vetor a[0], e ainda que respeitem os limites e regras de a, é gerado UB.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Agora entendi melhor.

 

Vlw guidjos!

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.