Je reçois un «type de pointeur incompatible» et je ne comprends pas pourquoi

Je reçois deux types d’erreurs:

Plaintes du compilateur

pr.c: dans la fonction ‘main’:

pr.c: 20: 2: avertissement: passage de l’argument 1 de ‘printMasortingx’ à partir d’un type de pointeur incompatible [activé par défaut]

pr.c: 9: 6: note: attendu ‘const int (*) [80]’ mais l’argument est de type ‘int (*) [80]’

pr.c: 22: 2: warning: passage de l’argument 1 de ‘lights’ à partir d’un type de pointeur incompatible [activé par défaut]

pr.c: 10: 6: note: attendu ‘const int (*) [80]’ mais l’argument est de type ‘int (*) [80]’

Il semble que le compilateur se plaint de recevoir un non-const dans une fonction qui prend un const, mais on m’a dit que c’était la bonne façon d’utiliser const

 #include  #include  #define MAXCOL 80 #define MAXROW 20 #define randNormalize() srand(time(0)) void fillMasortingx(int m[][MAXCOL], size_t rows, size_t cols); void printMasortingx(const int m[][MAXCOL], size_t rows, size_t cols); void lights(const int m[][MAXCOL], size_t rows, size_t cols); int star(const int m[][MAXCOL], int row, int col); int main() { int m[MAXROW][MAXCOL]; randNormalize(); fillMasortingx(m, 5, 5); printMasortingx(m, 5, 5); lights(m, 5, 5); return 0; } void fillMasortingx(int m[][MAXCOL], size_t rows, size_t cols) { int i, j; for(i = 0; i < rows; i++) for(j = 0; j < cols; j++) m[i][j] = rand()%21; } void printMatrix(const int m[][MAXCOL], size_t rows, size_t cols) { int i, j; for(i = 0; i < rows; i++) { printf("\n"); for(j = 0; j < cols; j++) printf("%d ", m[i][j]); } printf("\n"); } void lights(const int m[][MAXCOL], size_t rows, size_t cols) { int i, j; for(i = 1; i < rows - 1; i++) { printf("\n"); for(j = 1; j < cols - 1; j++) { if( star(m, i, j) ) printf("*"); else printf(" "); } } printf("\n"); } int star(const int m[][MAXCOL], int row, int col) { int i, j; int sum = 0; for(i = row - 1; i <= row + 1; i++) for(j = col - 1 ; j  10); } 

Je cherche la meilleure solution qui n’utilise pas de pointeur, car il s’agit d’un exercice d’un cours dans lequel nous ne les avons pas encore abordées (bien que je les ai étudiées).

Malheureusement, en C, il n’ya pas de conversion implicite d’ int[X][Y] à const int[X][Y] . Il n’existe pas non plus de conversion implicite de int (*)[Y] à const int (*)[Y] .

C’est un défaut de langage. il n’y a aucune raison technique pour laquelle une telle conversion ne devrait pas être autorisée. (C ++ autorise cette conversion).

Vous avez deux options, toutes deux peu attrayantes:

  1. Avoir les fonctions acceptent int au lieu de const int
  2. Ecrivez un cast lors de l’appel des fonctions const int , par exemple, printMasortingx((const int (*)[MAXCOL])m, 5, 5);

Normalement, l’option 1 serait utilisée et il suffirait de se passer de const-correct pour les tableaux multidimensionnels.

Problème

Lorsque vous utilisez m dans un appel de fonction comme vous le faites, il se décompose en un pointeur. Le type de pointeur auquel m se désintègre est int (*)[5] – un pointeur sur “un tableau de 5 int s”.

Étant donné la déclaration de fillMasortingx , le type d’argument attendu est int (*)[MAXCOL] , c’est-à-dire int (*)[80] – un pointeur sur “un tableau de 80 ints “.

Ces deux types ne sont pas compatibles.

La raison pour laquelle ces deux types ne sont pas compatibles peut être comprise en regardant comment le compilateur s’attend à ce que les pointeurs se comportent et la disposition de mémoire attendue.

Pour explication, je vais changer les tailles du tableau en 2 et 4.

Pour

 int m1[2][2]; 

la disposition de la mémoire ressemble à:

 m1[0][0] m1[1][1] | | +---+---+---+---+ | | | | | +---+---+---+---+ 

Si vous déclarez un pointeur sur ce tableau,

 int (*p1)[2] = m1; 

La disposition de la mémoire à partir de la perspective du pointeur ressemble à ceci:

 p1 p1+1 p1+2 | | | vvv +---+---+---+---+ | | | | | +---+---+---+---+ 

Maintenant, créons un tableau de taille 4 x 4 et examinons l’apparence de la disposition de la mémoire du sharepoint vue du pointeur.

 int m2[4][4]; 

Disposition de la mémoire:

 m2[0][0] m2[3][3] | | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 

Aiguille:

 int (*p2)[4] = m1; 

La disposition de la mémoire à partir de la perspective du pointeur ressemble à ceci:

 p2 p2+1 p2+2 p2+3 p2+3 | | | | | vvvvv +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 

Si vous comparez la façon dont l’arithmétique de pointeur est utilisée pour les deux types de pointeurs différents, vous verrez que:

p1[1][0] est assez différent de p2[1][0] en ce qui concerne la manière dont les valeurs de ces pointeurs sont décalées avant d’effectuer le déréférencement pointeur -> int .

Si p1 est traité comme s’il était du même type que le type de p2 , l’arithmétique du pointeur conduirait très facilement à accéder au tableau en dehors des limites et entraînerait un comportement indéfini.

C’est pourquoi un compilateur n’utilisera pas de pointeur de type int (*)[4] lorsque le type d’argument attendu est int (*)[80] .

Solution

Il y a plusieurs façons de résoudre le problème. La solution la plus simple consiste à utiliser

 int m[2][MAXCOL];