9
votes

Quelle est la raison pour laquelle le compilateur C demande que le nombre de colonnes dans une matrice 2D sera défini?

Compte tenu de la signature de fonction suivante: xxx

ceci ne compile pas.

et le corrigé un: xxx

Ma question est que le compilateur exige que le nombre de colonnes sera défini lors de la manipulation d'un tableau 2D en C? Y a-t-il un moyen de passer un tableau 2D à une fonction avec une dimension inconnue?

merci

c

1 commentaires

Veuillez ajouter le message d'erreur, le nom du compilateur et de la version à votre question.


6 Réponses :


1
votes

Ceci est dû au fait que dans la mémoire, il s'agit simplement d'une zone contiguë, d'une matrice à une dimension si vous voulez. Et pour obtenir le décalage réel de INPUTMATRIX [X] [Y], le compilateur doit calculer (x * elementsPercolumn) + y . Donc, il doit connaître l'élément olofpercolumn et cela signifie que vous devez le dire.


0 commentaires

5
votes

Comme la matrice en C est purement mémoire sans aucune information méta sur les dimensions, le compilateur doit savoir comment appliquer l'index de la ligne et de la colonne lors de l'adressage d'un élément de votre matrice.

INPUTMATRIX [I] [J] est traduit intérieurement à quelque chose équivalent à * (INPUTMATRIX + I * NUM + J)

Et ici, vous voyez que num est nécessaire.


1 commentaires

+1: bonne explication et aide définitivement à utiliser numéro comme taille pour correspondre à la question initiale.



1
votes

Non, il n'y a pas. La situation est vraiment simple: ce que la fonction reçoit n'est vraiment qu'un seul bloc de mémoire linéaire. Dites-lui que le nombre de colonnes lui indique comment traduire quelque chose comme bloc [x] [y] dans une adresse linéaire dans le bloc (c'est-à-dire qu'il doit faire quelque chose comme adresse = ligne * colonne_count + colonne ).


0 commentaires

18
votes

Les tableaux multi-déminsionnels intégrés en C (et en C ++) sont mis en œuvre à l'aide de l'approche "Index-Traduction". Cela signifie que la matrice 2D (3D, 4D 4D) est aménagée en mémoire sous forme de matrice 1D ordinaire de taille suffisante et l'accès aux éléments de ce tableau est mis en oeuvre en recalculant les indices multidimensionnels sur un indice 1D correspondant. Par exemple, si vous définissez un tableau 2D de taille m x n xxx

en réalité, sous la hotte, le compilateur crée une matrice de taille m * N xxx

Chaque fois que vous accédez à l'élément de votre tableau xxx

Le compilateur le traduit en < / p> xxx

Comme vous pouvez le constater, afin d'exécuter la traduction, le compilateur doit savoir n , mais n'a pas vraiment besoin de savoir M . Cette formule de traduction peut facilement être généralisée pour les tableaux avec n'importe quel nombre de dimensions. Cela impliquera toutes les tailles de la matrice multidimensionnelle, à l'exception du premier. C'est pourquoi chaque fois que vous déclarez une matrice, vous devez spécifier toutes les tailles, à l'exception du premier.


1 commentaires

Bonne explication. Il y avait une période où j'avais l'habitude d'écrire C code C avec mes matrices aplaties car il courait plus vite jusqu'à ce que je commence à compiler -O2, à partir de laquelle la GCC a fait cette partie pour moi et que je pouvais commencer à écrire un code lisible à nouveau \ o /



1
votes

D'autres personnes ont expliqué pourquoi, mais la façon de passer un tableau 2D avec des dimensions inconnues consiste à passer un pointeur. Le compilateur réduit les paramètres de matrimonie aux pointeurs de toute façon. Assurez-vous simplement qu'il est clair que vous attendez dans votre API Docs.


0 commentaires

2
votes

C n'a pas de support spécifique pour les tableaux multidimensionnels. Une matrice bidimensionnelle telle que double entréeMatrix [n] [m] est juste un tableau de longueur n dont les éléments sont des tableaux de longueur m de doubles.

Il existe des circonstances dans lesquelles vous pouvez laisser le nombre d'éléments dans un type de tableau. Il en résulte un type type - un type dont les exigences de stockage ne sont pas connues. Donc, vous pouvez déclarer double vecteur [] , qui est un tableau de taille non spécifiée de doubles. Cependant, vous ne pouvez pas mettre des objets de types incomplets dans un tableau, car le compilateur doit connaître la taille de l'élément lorsque vous accédez aux éléments.

Par exemple, vous pouvez écrire Double InputMatrix [] [M] [M] , qui déclare une matrice de longueur non spécifiée dont les éléments sont des matrices de longueur m de doubles. Le compilateur sait ensuite que l'adresse de INPUTMATRIX [i] est i * Tailleof (double [m]) octets au-delà de l'adresse de INPUTMATRIX [0] (et donc l'adresse de INPUTMATRIX [I] [J] [J] est i * Tailleof (double [m]) + j * Tailleof (double) octets). Notez qu'il doit connaître la valeur de M ; C'est pourquoi vous ne pouvez pas quitter M dans la déclaration de INPUTMATRIX .

Une conséquence théorique de la manière dont les tableaux sont définis sont que INPUTMATRIX [I] [J] désigne la même adresse que INPUTMATRIX + M * I + J . / p>

Une conséquence pratique de cette mise en page est que pour un code efficace, vous devez organiser vos tableaux de sorte que la dimension qui varie le plus souvent viennent en dernier. Par exemple, si vous avez une paire de boucles imbriquées, vous ferez une meilleure utilisation du cache avec pour (i = 0; i qu'avec des boucles imbriquées dans l'autre sens. Si vous devez basculer entre l'accès aux lignes et l'accès à la colonne MID-PROGRAM, il peut être bénéfique de transposer la matrice (ce qui est mieux fait le bloc par bloc plutôt que dans les colonnes ou dans des lignes).

RÉFÉRENCES C89: §3.5.4.2 (types de tableau), §3.3.2.1 (expressions d'indice de tableau)
C99 Références: §6.7.5.2 (Types de réseau), § 6.5.2.1-3 (expressions de tableau indiquant).

¹ Prouvant que cette expression est bien définie est laissée comme un exercice pour le lecteur. Si INPUTMATRIX [0] [m] est un moyen valide d'accéder à InputMatrix [1] [0] n'est pas si clair, bien qu'il soit extrêmement difficile pour une implémentation de la mise en œuvre. faites une différence.


0 commentaires