Pourquoi avons-nous besoin de spécifier la taille de la colonne lors du passage d'un tableau 2D comme paramètre?
Pourquoi pas mes paramètre être
void example(int Array[][]){ /*statements*/}
Pourquoi ai-je besoin de spécifier la taille de la colonne de la matrice? Disons, par exemple, 3
void example(int Array[][3]){/*statements*/}
Mon professeur a dit obligatoire, mais j'ai été codage avant que l'école a commencé et je me suis souvenu qu'il n'y a pas de syntaxe ou de sémantique erreur quand j'ai fait mon paramètre? Ou ai-je raté quelque chose?
- Il est nécessaire de calculer l'offset relatif de l'élément que vous êtes réellement accès. Le tableau lui-même est juste un bloc linéaire, mais plutôt que de vous avoir à faire (ligne*colwidth + col) (qui fonctionne, d'ailleurs), les décalages sont fait pour vous par le compilateur une fois qu'il sait le second ordre de grandeur.
- mais si je ne déclarez pas le décalage(le col de la taille) ce qui serait le compilateur par défaut?
- Soit vous n'avez pas utiliser 2+d tableaux en arrière à l'époque ou il n'était pas C.
Vous devez vous connecter pour publier un commentaire.
Quand il s'agit de décrire les paramètres, les tableaux toujours de désintégration dans des pointeurs vers son premier élément.
Lorsque vous passez un tableau déclaré que
int Array[3]
à la fonctionvoid foo(int array[])
, il se désintègre en un pointeur vers le début du tableau c'est à direint *Array;
. Btw, vous pouvez décrire un paramètre commeint array[3]
ouint array[6]
ou mêmeint *array
- tous ces va être l'équivalent, et vous pouvez passer n'importe quel tableau d'entiers sans problèmes.Dans le cas des tableaux de tableaux (tableaux 2D), il se désintègre à un pointeur vers son premier élément, qui se trouve être un seul dimensions, tableau c'est à dire obtenir
int (*Array)[3]
.En spécifiant la taille est importante. Si ce n'était pas obligatoire, il n'y aura pas de toute façon pour le compilateur de savoir comment traiter avec l'expression
Array[2][1]
, par exemple.Déréférencer un compilateur a besoin de calculer le décalage de l'élément dont nous avons besoin dans un bloc contigu de mémoire (
int Array[2][3]
est un bloc contigu de nombres entiers), qui devrait être facile pour les pointeurs. Sia
est un pointeur, puisa[N]
est élargi commestart_address_in_a + N * size_of_item_being_pointed_by_a
. Dans le cas de l'expressionArray[2][1]
l'intérieur d'une fonction (nous voulons accéder à cet élément) leArray
est un pointeur vers une unique matrice dimensionnelle et la même formule s'applique. Le nombre d'octets dans le dernier carré du support est nécessaire pour trouversize_of_item_being_pointed_by_a
. Si nous avions seulementArray[][]
il serait impossible de la trouver, et donc impossible de déréférencer un élément de tableau dont nous avons besoin.Sans la taille, l'arithmétique des pointeurs ne fonctionnerait pas pour des tableaux de tableaux. Quelle adresse
Array + 2
produire: l'avance l'adresse dansArray
2 octets à l'avance (mauvaise) ou l'avance le pointeur3* sizeof(int) * 2
octets à l'avance?int (*)[3]
est le type d'un pointeur sur un tableau.En C/C++, même 2-D les tableaux sont stockés séquentiellement, une ligne après l'autre dans la mémoire. Alors, quand vous avez (dans une seule fonction):
L'élément que vous avez réellement l'accès à
a[2][1]
est*(head + 2*3 + 1)
, cause de manière séquentielle, cet élément est après 3 éléments de la0
ligne, et 3 éléments de la1
ligne, et ensuite encore un indice de plus.Si vous déclarez une fonction comme:
point de vue syntaxique, il ne devrait pas être une erreur. Mais, lorsque vous essayez d'accéder
array[2][3]
maintenant, vous ne pouvez pas savoir quel élément est censé être accessible. D'autre part, lorsque vous avez:vous savez qu'avec
array[2][3]
, il peut être déterminé que vous êtes réellement l'accès à l'élément à l'adresse de la mémoire*(&array[0][0] + 2*5 + 3)
parce que la fonction connaît la taille de la seconde dimension.Il ya une autre option, comme suggéré précédemment, vous pouvez déclarer une fonction comme:
parce que de cette façon, vous êtes l'appel de la fonction avec le même "information" comme avant -- le nombre de colonnes. Vous accéder aux éléments d'un tableau un peu différent alors: vous avez à écrire
*(array + i*cols + j)
où vous avez l'habitude d'écrire desarray[i][j]
, causearray
est maintenant un pointeur d'entier (pas un pointeur).Lorsque vous déclarez une fonction comme ceci, vous devez être prudent de faire appel avec le nombre de colonnes qui sont en fait des déclaré pour le tableau, non seulement utilisé. Ainsi, par exemple:
Similaire il ya un post à ce sujet. Vous pouvez consulter ci-dessous le lien.
Création de Matrice en C et en passant le pointeur de ladite matrice de fonction
Espérons que cela aide.
Sur l'autre main, le compilateur a besoin de la deuxième dimension de sorte qu'il peut se déplacer "Tableau" à partir d'un pointeur à l'autre, car l'ensemble de la mémoire est organisé de façon linéaire
Lorsque vous créez un tableau 2D,
anytype a[3][4]
, en mémoire de ce que vous créez est3
blocs contigus de4
anytype objets.a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3]
Maintenant, la prochaine question est, pourquoi donc? Parce que, conformément à la spécification et la structure de la langue,
anytype a[3][4]
effectivement développe dansanytype (*a)[4]
, car les tableaux de désintégration dans les pointeurs. Et, en fait, qui développe également dansanytype (*(*a))
, toutefois, vous avez maintenant complètement perdu la taille du tableau 2D. Donc, vous devez aider le compilateur un peu.Si vous demandez au programme pour
a[2]
, le programme peut suivre les mêmes étapes que pour les tableaux 1D. Il ne peut tout simplement retournerthe 3rd element of sizeof(object pointed to)
, l'objet pointé ici est de taille 4 anytype objets.char a[x]
n'est pas le même quechar *b
. Pendant que l'instruction peut demander au premier niveau d'indirection lorsqu'un tableau est passé en argument de fonction, il ne s'applique pas auxa
dans le champ d'application -- c'est un tableau.anytype (*a)[]
qui est un pointeur vers un tableau de type incomplète.En fait si c'est un tableau 2d ou 1d tableau, il est stocké dans la mémoire, dans une seule ligne.Donc, pour dire au compilateur où faut-il briser la ligne indiquant le prochain numéros dans les prochaines lignes, nous sommes censés fournir de la taille de la colonne. Et de briser les lignes de manière appropriée donnera la taille des lignes.
Voyons un exemple:
Cette matrice a est stockée dans la mémoire comme:
Mais depuis, nous avons spécifié la taille de la colonne 3 de la mémoire divise, après tous les 3 numéros.
Dans les autres cas,
Le compilateur sait seulement qu'il y a 3 lignes, mais il ne sait pas le nombre d'éléments dans chaque ligne de sorte qu'il ne peut allouer de la mémoire et affiche une erreur.