8
votes

Définition d'un tableau 2D avec MALLOC et de la modifier

Comment définir un tableau 2D à l'aide de MALLOC? (disons 10x20).

Deuxièmement, puis-je augmenter le nombre de lignes ou de cols sans créer de nouvelle matrice accrue et copier toutes les données à elle?

Par exemple, comment allouer la mémoire afin que le tableau soit 10x30 ou 15x20?

Merci!

c

7 Réponses :


0
votes

second, puis-je augmenter le nombre de lignes ou cols sans créer de nouveau augmentation de la matrice et copier toutes les données à cela?

Non, vous ne pouvez pas modifier la taille d'un tableau. Ce que vous pouvez faire est d'utiliser des pointeurs et de realloc pour le faire.


0 commentaires

3
votes
// first allocate the 20 rows, that contain pointers to int 
// (if the matrix contains int type values)
int **a = malloc(20 * sizeof(int *));

// now loop for each row and allocate data for the actual values
int i;
for(i = 0; i < 20; i++) {
    a[i] = malloc(10 * sizeof(int));
}
For increasing the size of the matrix you can use realloc although it would probably be easier to regenerate the matrix of different size and copy the values over.

2 commentaires

Cette photo ressemble à une explication C ++. Notez que si cela explique l'opérateur C ++ nouveau , il est faux. nouveau crée un tableau réel de tableaux, qui ressemblera au premier diagramme (attribuer uniquement 3 * 4 entiers, comme des tableaux déclarés), mais pas comme le deuxième diagramme (alloué 3 * 4 entiers et 4 pointeurs). Bien sûr, la description est correcte si elle est appliquée à votre code de boucle au lieu de neuf int [3] [4] .


Oui, je voulais en fait faire référence à ce deuxième diagramme, laissez-moi vous en débarrasser.



4
votes

tandis que malloc () ne prend pas directement en charge les tableaux multidimensionnels, il existe des contours de contournement, tels que: xxx

tandis que ce n'est pas directement un tableau 2D. , ça marche et, à mon avis, c'est le plus simple. Mais si vous voulez utiliser la syntaxe [] [] [] , vous devez effectuer des pointeurs sur des pointeurs, par exemple: xxx


4 commentaires

+1 - Je trouve cela beaucoup plus simple et moins d'erreur que la solution de matrice de tableaux.


Je pense que je vais utiliser votre premier exemple, c'est beaucoup plus simple. Merci et tous les autres pour vos réponses


MM Juste une autre question, avec le deuxième exemple, je peux créer un tableau non carré? Comme en Java: arr [] [] = {1,2,3,4}, {1,2}?


@ROB OUI bien sûr, vous pouvez créer des matrices déchiquetées en C comme dans Java. Dans la ligne Code: Array [I] = MALLOC (COLS * TAILLEOF (INT)) Remplacez simplement le nombre quelconque au lieu de la variable COLS. C'est ça.



0
votes

Un tableau 2D est un tableau 1D de matrices 1D. En tant que tableau, il s'agit simplement d'un pointeur, un tableau de matrices est une gamme de pointeurs. Donc, vous utilisez masloc pour allouer un tableau de pointeurs (chacun représentant un collumn), puis l'utiliser à nouveau pour allouer les tableaux individuels (chacun représentant une rangée).

Pour développer / rétrécir le tableau , vous utilisez realloc (Référence) . Voici un exemple de code: xxx

Je suis désolé si j'ai quelque chose de mal. Mon c-fu est un peu rouillé :)


0 commentaires

11
votes

10x30: xxx pré>

15x20: p> xxx pré>

redimensionnement à 20x25: p> xxx pré> La dimension extérieure (10, 15, 20) peut être déterminée au moment de l'exécution, car elle n'a pas besoin de cas de calcul de l'index par le compilateur. La dimension interne (30, 20, 25) doit être connue au moment de la compilation. J'espère que ça aide. p>

Notez que la différence des solutions de pointeur, celui-ci peut être géré comme un seul bloc de mémoire, car il attribue tout dans une seule partie de la mémoire comme un réel tableau déclaré: P>

  // array[4][9] = 1;
  (BinaryOperator 0xbf9f7e8 <line:5:3, col:17> 'int' '='
    (ArraySubscriptExpr 0xbf9f7a8 <col:3, col:13> 'int'
      (ImplicitCastExpr 0xbf9f788 <col:3, col:10> 'int *' <ArrayToPointerDecay>
        (ArraySubscriptExpr 0xbf9f748 <col:3, col:10> 'int [10]'
          (ImplicitCastExpr 0xbf9f728 <col:3> 'int (*)[10]' <ArrayToPointerDecay>
            (DeclRefExpr 0xbf9f6cc <col:3> 'int [5][10]' Var='array' 0xbfa81f0))
          (IntegerLiteral 0xbf9f6f0 <col:9> 'int' 4)))
      (IntegerLiteral 0xbf9f768 <col:12> 'int' 9))
    (IntegerLiteral 0xbf9f7c8 <col:17> 'int' 1)))


8 commentaires

Attendez, je suis un peu confus. N'est-ce pas int (* tableau) [30] un pointeur au tableau 30 de INT? Et vous affectez ce pointeur à un emplacement de Tailleof (int) * 10 BYTES BIG. Cela signifie que cet emplacement ne peut contenir que 10 INTS. D'où vient l'allocation pour le reste des octets? Parce qu'il a besoin de 30x10 intens (300 INTS). Je ne savais pas que mettre la [] dans la définition reproduirait l'emplacement attribué aux tableaux ... Comment cela fonctionne-t-il?


@LUCA, YEP C'est un pointeur à un tableau de 30 Int. Mais Tailleof * Array Produits Tailleof (int [30]) qui est Tailleof (int) * 30 . Je ne sais pas ce que vous entendez par "reproduire l'emplacement attribué aux tableaux". Lemme Essayez de l'expliquer: le premier code attribue simplement un tampon ayant la taille Tailleof (int [10] [30]) et rend un pointeur sur int [30] point . Vous pouvez ensuite indexer dans la plage de Array [0..9] [0..29] .


Ohhhhhhh, intelligent :). Merci de m'avoir appris quelque chose de nouveau. +1.


@Joohannes: mais attends .. Pouvez-vous toujours accéder à un emplacement de mémoire à l'aide de la double pointe Dereferencing, Array [5] [10] ? Je ne sais pas comment cela fonctionnerait-il car il est tout simplement un seul bloc de mémoire comme vous l'avez dit. Qu'est-ce que tableau [5] être?


Array [5] serait int [30] . Notez qu'il est * (array + 5) , qui ajoute Tailleof (int [30]) * 5 octets à l'adresse stockée dans la matrice. Avec le int [30] et le int * décrit ces rendements, la deuxième opération d'index peut alors avoir lieu et finalement donner le int lvalue. Voici comment intora [10] [30]; fonctionne aussi. Une fois que vous vous référez à tableau dans un index op, il se désintègre et devient int (*) [30] .


Notez que les pointeurs de tableau sont différents des autres pointeurs de données. Si d est un int * , puis lisez ce que * d désigne impliquer une lecture de mémoire. Mais si d est un t (*) [n] , puis "lecture" (c'est-à-dire ajouter quelque chose) Quel * d fait référence à l'implication non Lire la mémoire. Cela implique simplement une décomposition du t [n] t [n] à un t * . Parfois, j'ai mal à la tête aussi :)


@Johannes, dans votre commentaire ci-dessus, je peux voir comment * (tableau + 5) donne un int [30] , puisque vous êtes la déséroférance du pointeur, mais comment ce rendement (ou correspond à?) Un Int * Decay? "Avec le int [30] et le int * décrit ces rendements ..."


Je reçois ce message d'erreur lorsque j'essaye votre exemple. "Test.cpp: 111: 36: Erreur: Conversion invalide de" void * "sur" int (*) [2052] "[-Fermissive] int (* data_array) [2052] = malloc ((taille de * data_array) * Num_Packets ); " J'ai essayé d'ajouter -fpermissive à mes drapeaux de GCC et obtenu un avertissement au lieu de l'erreur.



0
votes

au lieu d'utiliser int [rangée] [col] Vous devez mieux "envelopper votre matrice" dans une matrice unidimensionnelle int [ligne * col] .

Voici l'exemple de code: xxx

si la réaffectation est un problème que des problèmes peuvent apparaître. Et vous devez utiliser la version bi dimensionnelle.


0 commentaires

0
votes

Bien que ce soit une ancienne question, voici ma solution différente.

[user@buzz ~]$ gcc main.c -o main
[user@buzz ~]$
[user@buzz ~]$ ./main
0 1 2 3 4 5 6 7
10 11 12 13 14 15 16 17
20 21 22 23 24 25 26 27
30 31 32 33 34 35 36 37
40 41 42 43 44 45 46 47
[user@buzz ~]$


0 commentaires