Ir para conteúdo

POWERED BY:

Arquivado

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

Beraldo

[Resolvido] int matriz[10][10] e int **matriz

Recommended Posts

Acho que ando meio enferrujado em C... :unsure:

 

Eu estava fazendo um programa e me deparei com um warning de incompatibilidade de tipos.

 

Fiz testes num arquivo isolado e o erro persiste. Com alocação dinâmica funciona; com estática, não. :unsure:

 

Vejam:

(com alocação estática)

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

#define NUM 5

void popular( int **matriz )
{
	int i, j;
	
	for ( i = 0; i < NUM; i++ )
	{
		for ( j = 0; j < NUM; j++ )
		{
			matriz[i][j] = i+j;
		}
	}
}
/*------------------*/


int main()
{
	int matriz[NUM][NUM];
	
	popular( matriz );
	
	return 0;
}

Saída da compilação:

$ gcc -Wall test.c -o test
test.c: In function ‘main’:
test.c:25: warning: passing argument 1 of ‘popular’ from incompatible pointer type

A linha 25 é a chamada a "popular":

popular( matriz );

 

 

com alocação dinâmica (mudando apenas o main)

int main()
{
	int **matriz;
	int i;
	
	matriz = (int **) malloc( NUM * sizeof( int* ) );
	for ( i = 0; i < NUM; i++ )
	{
		*(matriz + i ) = (int*) malloc( NUM * sizeof( int ) );
	}
	
	popular( matriz );
	
	return 0;
}

Assim compila certinho, sem warnings.

 

 

Alguém sabe por quê?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fala Beraldo, tudo certo?

O problema é que, com alocação estática, o seu simbolo "matriz" é do tipo int[][], e com alocação dinâmica, é do tipo int**.

Você pode fazer um casting, e provavelmente acabará com os problemas:

popular((int**)matriz);

Abraços

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tu não pode fazer assim.

 

Dá uma olhada nisso: http://www.lysator.liu.se/c/c-faq/c-2.html#2-15

 

O link mostra dois tipo de chamada:

 

popular( &matriz[0][0] );
e

popular( (int**) matriz );
esse é o mesmo sugerido pelo Victor.

 

O primeiro jeito exibe o mesmo warning. O segundo não exibe warning, mas é como se a matriz não tivesse sido alocada. Vou postar o código e a saída logo abaixo.

 

 

 

Fala Beraldo, tudo certo?

 

Tranquilo e você? :)

 

O problema é que, com alocação estática, o seu simbolo "matriz" é do tipo int[][], e com alocação dinâmica, é do tipo int**.

Você pode fazer um casting, e provavelmente acabará com os problemas:

popular((int**)matriz);

Abraços

 

O problema é o citado acima. Parece que a matriz não é alocada. Veja como fiz o main (não alterei a função popular):

 

int main()
{
	int matriz[NUM][NUM];
	int i, j;
	
	popular( (int**)matriz );
	
	for ( i = 0; i < NUM; i++ )
	{
		for ( j = 0; j < NUM; j++ )
		{
			printf( "%d ", matriz[i][j] );
		}
		puts( "" );
	}
	
	return 0;
}

O programa não chega nem no for para exibir. Ele dá falha de segmentação na gravação dos dados. Veja:

 

$ gcc -Wall -g test.c -o test && ./test

Falha de segmentação

$ gdb test

GNU gdb 6.8-debian

Copyright © 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law. Type "show copying"

and "show warranty" for details.

This GDB was configured as "x86_64-linux-gnu"...

(gdb) break main

Breakpoint 1 at 0x4005ab: file test.c, line 26.

(gdb) run

Starting program: /usr/share/GRAFO/plugins/ci065-trab1/test

 

Breakpoint 1, main () at test.c:26

26 popular( (int**)matriz );

(gdb) step

popular (matriz=0x7fff48f356b0) at test.c:10

10 for ( i = 0; i < NUM; i++ )

(gdb) step

12 for ( j = 0; j < NUM; j++ )

(gdb) step

14 matriz[j] = i+j;

(gdb) step

 

Program received signal SIGSEGV, Segmentation fault.

0x000000000040058b in popular (matriz=0x7fff48f356b0) at test.c:14

14 matriz[j] = i+j;

(gdb) print i

$1 = 0

(gdb) print j

$2 = 0

(gdb)

 

É como se matriz[0][0] não existisse. :blink:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tranquilo e você? :)

Tranquilo por aqui também! =D

 

Cara, realmente essa falha de segmentação é estranha.

Se retirarmos a chamada à função "popular" e inicializarmos a matriz na main, funciona:

int main()
{
int matriz[NUM][NUM];
int i, j;

	for ( i = 0; i < NUM; i++ )
		for ( j = 0; j < NUM; j++ )
			matriz[i][j] = i+j;

	for ( i = 0; i < NUM; i++ )
	{
		for ( j = 0; j < NUM; j++ )
			printf( "%d; ", matriz[i][j] );
			
		puts( "" );
	}

	return 0;
}

victor@matrix:~/Desktop$ gcc matriz_beraldo.c -Wall -Wextra -g

victor@matrix:~/Desktop$ ./a.out

0; 1; 2; 3; 4;

1; 2; 3; 4; 5;

2; 3; 4; 5; 6;

3; 4; 5; 6; 7;

4; 5; 6; 7; 8;

 

Se nós "simularmos" uma matriz, também funciona:

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

#define NUM 5

int* access_xy(int *arr, int line, int col)
{
	return &arr[line*NUM + col];
}

void popular(int* matriz)
{
int i, j;

	for ( i = 0; i < NUM; i++ )
		for ( j = 0; j < NUM; j++ )
			*access_xy(matriz, i, j) = i+j;
}


int main()
{
int matriz[NUM*NUM];
int i, j;

	popular(matriz);

	for ( i = 0; i < NUM; i++ )
	{
		for ( j = 0; j < NUM; j++ )
			printf( "%d; ", (*access_xy(matriz, i, j)));
			
		puts( "" );
	}

	return 0;
}

victor@matrix:~/Desktop$ gcc matriz_beraldo.c -Wall -Wextra -g

victor@matrix:~/Desktop$ ./a.out

0; 1; 2; 3; 4;

1; 2; 3; 4; 5;

2; 3; 4; 5; 6;

3; 4; 5; 6; 7;

4; 5; 6; 7; 8;

 

o.O

vou continuar a testar, conforme eu descobrir algo, poso aqui.

 

------------------------------------

EDIT

------------------------------------

Parece que o problema está na declaração da função popular.

declare-a da seguinte forma:

void popular(int matriz[][NUM]);

Não sei exatamente o motivo, já que as duas declarações são equivalentes.

Acredito que seja qualquer coisa relacionada ao tamanho de "matriz"

Compartilhar este post


Link para o post
Compartilhar em outros sites

------------------------------------

EDIT

------------------------------------

Parece que o problema está na declaração da função popular.

declare-a da seguinte forma:

void popular(int matriz[][NUM]);

Não sei exatamente o motivo, já que as duas declarações são equivalentes.

Acredito que seja qualquer coisa relacionada ao tamanho de "matriz"

 

hmmm

 

assim deu certo.

 

Estranho, pois deveria funcionar com **, mas beleza.

 

De qualquer forma, vou usar malloc. Eu só queria entender por que estava ocorrendo aquele warning.

 

Valeu. http://forum.imasters.com.br/public/style_emoticons/default/joia.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

Dá uma lida na seção 2.10 daquele mesmo link: http://www.lysator.liu.se/c/c-faq/c-2.html#2-10

 

Também dê uma lida na seção Two dimensional Arrays deste link: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html

Estou vendo se consigo fazer uma gambiarrazinha aqui mas tá complicado...

 

Se tu for ver, se tu converter a array para (int**) na passagem para a função, e usar o debugger para verificar o que acontece na função, tu vai ter a array corretamente apontando para o endereço da memória onde ela está (se tu for comparar com a array da main (que no meu caso é 0x22ff00 ou algo assim). Só que se tu for tentar acessar o primeiro elemento, tu vai ter 0xffffff no meu caso porque o primeiro elemento não inicializado da minha array era -1, e na função esse -1 é interpretado como outro ponteiro para o endereço de memória correspondente a -1. A mesma coisa acontece com os outros elementos. Só que tu tem pelo menos o endereço inicial da matriz então vou ver se não dá para fazer uma gambiarra aqui com aritmética de ponteiros xD

 

Então, tu pode fazer uma gambiarra assim, que sinceramente eu acho totalmente inútil mas ela tá aí e dá pra fazer pra tu entender um pouco mais sobre como funcionam as coisas.

 

*((int*)matriz + (i * NUM) + j) = i+j;

 

Usando esse código, ao invés de acessar o -1 da matriz como endereço de memória, tu vai acessar corretamente o -1.

Porém, se tu tentar passar uma matriz dinâmica para essa função, esse código será totalmente inútil porque daí será acessado o primeiro elemento dessa matriz como ponteiro, aí tu só inverteu os papéis. E é mais inútil ainda porque tu espera um int** mas só vai poder receber *int[]. Mais vale criar outra função especificamente para matrizes estáticas e usar as duas quando necessário, ou então adicionar um pouco de variedade na função, se você quiser usar C++ pode fazer um overload da função, fazendo uma que recebe int** e outra que recebe *int[], e daí o resto do problema é do compilador de decidir qual vai em qual; ou então adicionar um parâmetro flag na função, que pode vir 1 ou 0, utilizando ou o código normal para manipular o int** ou aquele código modificado ali em cima para as matrizes estáticas. Em C tu evita ter que reescrever a função denovo com esse flag aí, mas em C++ tu evita ter que adaptar todas as regiões do seu código que tu vai usar isso. Se tu quiser ainda, em C++ tu pode definir um valor padrão para o flag, assim tu só precisa chamar popular(int(**) matrizestatica, 1) quando tu precisar de uma matriz estática sendo inicializada na função (eu sinceramente prefiro as funções aceitando parâmetros diferentes, assim tu usa o código simples matriz[x][y] ao invés daquela loucura toda ali de cima). Vê aí o que fica melhor pra ti.

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.