Como passar um array multidimensional para uma function em C e C ++

#include void print(int *arr[], int s1, int s2) { int i, j; for(i = 0; i<s1; i++) for(j = 0; j<s2; j++) printf("%d, ", *((arr+i)+j)); } int main() { int a[4][4] = {{0}}; print(a,4,4); } 

Isso funciona em C, mas não em C ++.

erro:

 cannot convert `int (*)[4]' to `int**' for argument `1' to `void print(int**, int, int)' 

Por que não funciona em C ++? Que mudança é necessária para ser feita?

Este código não funcionará em C ou C ++. Uma matriz do tipo int[4][4] não é convertível para um ponteiro do tipo int ** (que é o que int *arr[] significa na declaração do parâmetro). Se você conseguiu compilá- lo em C, é simplesmente porque você provavelmente ignorou um aviso do compilador C basicamente do mesmo formato da mensagem de erro que você obteve do compilador C ++. (Às vezes, compiladores C emitem avisos para o que é essencialmente um erro .)

Então, novamente, não faça afirmações que não sejam verdadeiras. Este código não funciona em C. Para converter um array 2D embutido em um ponteiro int ** você pode usar uma técnica como esta

Convertendo matrizes multidimensionais em pointers em c ++

(Veja a resposta aceita. O problema é exatamente o mesmo.)

EDIT: O código parece funcionar em C porque outro bug no código de impressão está mascarando os efeitos do bug na passagem de matriz. Para acessar corretamente um elemento de uma pseudo-array int ** , você tem que usar a expressão *(*(arr + i) + j) , ou melhor, uma arr[i][j] simples (que é a mesma coisa ). Você perdeu o extra * que o fez imprimir algo que não tem absolutamente nada a ver com o conteúdo do seu array. Novamente, inicialize sua matriz em main para outra coisa, para ver que os resultados que você está imprimindo em C não têm absolutamente nada a ver com o conteúdo pretendido da matriz.

Se você alterar a instrução printf como mostrado acima, seu código provavelmente falhará devido ao bug de passagem de array que descrevi inicialmente.

Mais uma vez: você não pode passar um array int[4][4] como um int ** pseudo-array. Isto é o que o C ++ está dizendo na mensagem de erro. E, tenho certeza, isso é o que seu compilador C lhe disse, mas você provavelmente o ignorou, já que era “apenas um aviso”.

O problema é que

 int a[4][4]; 

será realmente armazenado em uma memory fisicamente contínua. Então, para acessar uma parte arbitrária do seu array 4×4, a function “print” precisa conhecer as dimensões do array. Por exemplo, o pequeno trecho a seguir, acessará a mesma parte da memory de duas maneiras diferentes.

 #include  void print(int a[][4]){ for (int i = 0; i <4; i++){ for (int j = 0; j < 4; j++){ //accessing as 4x4 array std::cout << a[i][j] < 

Então, o layout da memory não muda, mas a maneira de acessar faz. Pode ser visualizado como um tabuleiro de damas.

  0 1 2 3 ---------- 0| 1 2 3 4 1| 5 6 7 8 2| 9 10 11 12 3|13 14 15 16 

Mas a memory física real é assim.

 0*4+0 0*4+1 0*4+2 0*4+3 1*4+0 1*4+1 1*4+2 1*4+3 2*4+1 etc. ----------------------------------------------------- 1 2 3 4 5 6 7 8 9 etc. 

Em c ++, os dados de uma matriz são armazenados linha por linha e o comprimento de uma linha (neste caso, 4) é sempre necessário para chegar ao deslocamento de memory apropriado para a próxima linha. O primeiro subscrito, portanto, indica apenas a quantidade de armazenamento necessária quando a matriz é declarada, mas não é mais necessário calcular o deslocamento posteriormente.

 #include void print(int arr[][4], int s1, int s2) { int i, j; printf("\n"); for(i = 0; i 

Isso funcionará, onde por trabalho quero dizer compilar. @AndreyT explicou por que sua versão ainda não funciona.

É assim que você deve passar uma matriz 2d.

Para maior clareza, você também pode especificar os dois tamanhos na declaração da function:

 #include void print(int arr[4][4], int s1, int s2) { int i, j; printf("\n"); for(i = 0; i 

Ambos irão funcionar.

Você também deve mudar *((arr+i)+j) para a[i][j] (preferencialmente) ou *(*(arr+i)+j) se sua intenção é acessar o jésimo elemento da linha i .

Aqui está uma versão que está funcionando, mas teoricamente inválida (veja abaixo) C90 e C ++ 98:

 #include  static void print(int *arr, size_t s1, size_t s2) { size_t i, j; printf("\n"); for(i = 0; i < s1; i++) { for(j = 0; j < s2; j++) { printf("%d, ", arr[i * s2 + j]); } } printf("\n"); } int main(void) { int a[4][4] = {{0}}; print(a[0], 4, 4); return 0; } 

Uma versão em C ++ usando modelos (adaptados da resposta de Notinlist ) poderia ser assim:

 #include  #include  using namespace std; template  struct IntMatrix { int data[N][M]; IntMatrix() { memset(data, 0, sizeof data); } }; template  ostream& operator<<(ostream& out, const IntMatrix& m) { out << "\n"; for(size_t i = 0; i < N; i++) { for(size_t j = 0; j < M; j++) { out << m.data[i][j] << ", "; } } out << "\n"; return out; } int main() { IntMatrix<4,4> a; cout << a; return 0; } 

Como alternativa, você poderia usar contêineres STL nesteds - isto é, vector< vector > - em vez de uma matriz simples.

Com C99, você poderia fazer

 static void print(size_t s1, size_t s2, int arr[s1][s2]) { printf("\n"); for(size_t i = 0; i < s1; i++) { for(size_t j = 0; j < s2; j++) { printf("%d, ", arr[i][j]); } } printf("\n"); } 

e chamá-lo como

 print(4, 4, a); 

Como Robert apontou nos comentários, o primeiro trecho realmente envolve um comportamento indefinido. No entanto, assumindo que a aritmética de pointers sempre resultará em um ponteiro mesmo quando o comportamento indefinido estiver envolvido (e não explodir seu computador), haverá apenas um único resultado possível devido a outras restrições dentro do padrão, isto é, uma instância de onde padrão deixa algo desnecessariamente indefinido.

Tanto quanto eu posso dizer, substituindo

 print(a[0], 4, 4); 

com

 union m2f { int multi[4][4]; int flat[16]; } *foo = (union m2f *)&a; print(foo->flat, 4, 4); 

fará legal C.

Você pode usar int** vez disso. É muito mais flexível:

 #include  #include  void print(int **a, int numRows, int numCols ) { int row, col ; for( int row = 0; row < numRows; row++ ) { for( int col = 0; col < numCols ; col++ ) { printf("%5d, ", a[row][col]); } puts(""); } } int main() { int numRows = 16 ; int numCols = 5 ; int **a ; // a will be a 2d array with numRows rows and numCols cols // allocate an "array of arrays" of int a = (int**)malloc( numRows* sizeof(int*) ) ; // each entry in the array of arrays of int // isn't allocated yet, so allocate it for( int row = 0 ; row < numRows ; row++ ) { // Allocate an array of int's, at each // entry in the "array of arrays" a[row] = (int*)malloc( numCols*sizeof(int) ) ; } int count = 1 ; for( int row = 0 ; row < numRows ; row++ ) { for( int col = 0 ; col < numCols ; col++ ) { a[row][col] = count++ ; } } print( a, numRows, numCols ); } 

Outra coisa que você pode estar interessado é uma estrutura como D3DMATRIX :

 typedef struct _D3DMATRIX {
     União {
         struct {
             float _11, _12, _13, _14;
             float _21, _22, _23, _24;
             float _31, _32, _33, _34;
             float _41, _42, _43, _44;

         };
         float m [4] [4];
     };
 } D3DMATRIX;

 D3DMATRIX myMatrix;

O doce sobre este pequeno detalhe é que você pode usar tanto myMatrix.m[0][0] (para acessar o primeiro elemento), ou você pode usar myMatrix._11 para acessar o mesmo elemento também. A união é o segredo.

 #include template  struct DataHolder { int data[N][M]; DataHolder() { for(int i=0; i void print(const DataHolder& dataHolder) { printf("\n"); for(int i = 0; i a; print(a); } 

Além de usar arrays de comprimento variável no C99, você não pode portavelmente gravar uma function para aceitar um array multidimensional se os tamanhos dos arrays não forem conhecidos em tempo de compilation. Consulte a Pergunta 6.19 do C-FAQ . A melhor maneira de lidar com isso é simular matrizes multidimensionais usando memory alocada dinamicamente. A pergunta 6.16 faz um bom trabalho ao explicar os detalhes de como fazer isso.

Resposta curta, você pode mudar o programa da seguinte forma

 void print(int arr[], int s1, int s2) { ... printf("%d,", *(a+i + s2*j)); ... print((int*)a,4,4); 

Isso precisaria de uma resposta melhor explicando as diferenças entre aritmética de pointers e ponteiro e arrays em C e C ++. Eu não vou entrar nisso agora. Talvez outra pessoa?

Obviamente, não estou chocado com o mesmo ponto que outros pôsteres em seu código. O que mais me incomoda no header da function de impressão é que você usa uma dupla indireta para uma matriz onde você não pretende alterar o ponteiro inicial de volta (na verdade, isso não pode ser feito, pois é uma constante). @ | V | lad answer conserta isto ajustando uma ou duas dimensões para uma constante fixa, mas então passar s1 e s2 se tornam inúteis.

Tudo depende do que você realmente quer fazer. É imprimir uma function de impressão de matriz de propósito geral ou especializada para alguns tipos de matriz?

A primeira coisa a fazer é acertar os tipos. Se as regras do C ++ são as mesmas que as do C no que diz respeito aos tipos de array (eu tenho certeza que eles são), então é dada a declaração

 int a[4][4]; 

a expressão a tem tipo int [4][4] , que é implicitamente convertido (“decays”) em um tipo de ponteiro de int (*)[4] (ponteiro para array de 4 elementos de int) quando passado para print , então você precisa alterar a print para

 void print(int (*arr)[4], int s1, int s2) { int i, j; for(i = 0; i 

A expressão arr[i] implicitamente desreferências arr , então você não precisa mexer com um cancelamento de referência explícito.

A desvantagem é que a print só pode manipular matrizes Nx4 de int; Se você quiser lidar com outros tamanhos de matriz, precisará adotar uma abordagem diferente.

Uma coisa que você pode fazer é, em vez de passar a matriz, passar o endereço do primeiro elemento e print manualmente os deslocamentos, da seguinte maneira:

 int main() { int a[4][4] = {{0}}; print(&a[0][0],4,4); // note how a is being passed } void print(int *arr, int s1, int s2) // note that arr is a simple int * { int i, j; for (i = 0; i < s1; i++) for (j = 0; j < s2; j++) printf("%d, ", arr[i * s2 + j]); } 

Matrizes multidimensionais são blocos contínuos de memory. Então você pode fazer assim:

 #include  void pa(const int *a, int y, int x) { int i, j; for (i=0;i 

Também funciona em C ++;

Eu só quero mostrar a versão C ++ da resposta do Bobobobo.

 int numRows = 16 ; int numCols = 5 ; int **a ; a = new int*[ numRows* sizeof(int*) ]; for( int row = 0 ; row < numRows ; row++ ) { a[row] = new int[ numCols*sizeof(int) ]; } 

O resto do código é o mesmo do bobobobo.

 #include void print(int (*arr)[4], int s1, int s2) { int i, j; for(i = 0; i 

isso irá compilar editar: alguém já postou esta solução minha