Je veux allouer de manière dynamique une structure C: "Les valeurs" et les "valeurs" sont censées être des matrices, mais leur taille est inconnue jusqu'au moment de l'exécution. P> < p> Comment puis-je allouer de manière dynamique la mémoire pour mes tableaux de struct et de struct? p> p>
13 Réponses :
Utilisez la fonction MALLOC ou CALOCO pour allouer de la mémoire de manière dynamique.
et recherchez-le sur Google pour obtenir des exemples.
Il est probablement toujours intéressant de mentionner de nouvelles constructions. En particulier comme les structures ne sont pas courantes dans le monde C ++.
Oui, je le sais et je supprime une partie nouvelle / Supprimer de la réponse.
Vous aurez besoin d'une fonction pour le faire.
Quelque chose comme (mon C / C ++ est rouillé) Syntaxe peut être un peu désactivé mais c'est généralement ce que vous allez avoir besoin. Si vous utilisez C ++, vous voulez probablement une classe avec un constructeur qui prenait les 2 args au lieu de la guide mais faisant quelque chose de très similaire. P> P>
Vous devriez également créer une fonction de destroystructeur également. La symétrie signifiera qu'il est moins probable que quelqu'un ailleurs dans la ligne d'oublier de supprimer tous les membres de données.
Si vous allez utiliser des constructions C ++, vous devez tout faire la manière C ++ et le faire constructeur / destructeur. Cet hybride C / C ++ est contreto intuitif.
@Dave: C ++ a sa propre version de GC beaucoup plus fines de GC. Ses appelés intelligents appelés. Aussi gâté n'est pas le terme correct, j'aurais dit criiplé :-) (blague)
@Martin: Ouais, j'ai utilisé des pointeurs intelligents un moment. Ils ont presque fait C ++ dans une langue raisonnable à utiliser (bien que la basebase que je supportais a mélangé les mélanges avec des pointeurs standard - pur mal). Bien que du niveau de question, je doute qu'ils soient un bon sujet pour ici.
swc *a = (swc*)malloc(sizeof(swc)); a->offset = (short*)malloc(sizeof(short)*n); a->values = (char*)malloc(sizeof(char)*n); Where n = the number of items in each array and a is the address of the newly allocated data structure. Don't forget to free() offsets and values before free()'ing a.
La coulée du résultat de Malloc n'est pas requise dans C, mais est en C ++. Et la taille de (char) est toujours 1.
@ Joe: Taillef (Char) peut toujours être un. Mais c'est toujours agréable de l'avoir dans le code. Il s'agit d'actes comme la documentation de votre intention (et ce n'est pas comme si cela coûte quoi que ce soit au moment de l'exécution!).
@Joe Gauterin: Non, mais c'est une bonne pratique de le faire quand même. ; p
Aussi à l'aide de Tiplôme (* A) et de tailleOf (A-> valeurs [0]) signifie que vous ne répétez pas le type dans le code. Remarque taille de la compilation est de sorte que c'est sûr.
Premièrement, la moulage de la valeur de retour de MALLOC () code> est une pratique discutable, alors arrêtez-vous d'agir comme votre côté préféré du débat est le "droit". Il a été débattu à plusieurs reprises et ces commentaires ne sont pas un endroit pour reproduire le débat. Si vous avez besoin de compatibilité C ++, vous n'avez pas de choix, mais si vous ne le faites pas, je vous recommande de ne pas le faire, car si le type de
a-> décalse code> change sur un < Code> long code> Vous devrez modifier le casting de
MALLOC () code> (et de tout
realloc () code> s Vous pouvez également appeler) ou faire face à des bugs graves , qui conduit à plus de maintenance que nécessaire. (Conut dans le prochain commentaire)
Deuxièmement, pour la même raison, vous devez utiliser Tailleof (* A) Code> et
Tailleof (* A-> Décalage) code> au lieu de
Tailleof (SWC) Code> et
Taillef (court) code>. Si le type de
a code> change (ou plus probable, le type de
a-> décalse code> modifications de
court code> à
long code>), en utilisant la variable plutôt que le type vous permettra de ne changer que la ligne qui déclare la variable, plutôt que de changer toutes les lignes que
MALLOC () code> et
realloc () code> dessus. S'ils déduisent tous le type correct de la variable (ou
struct code> membre), nous avons moins de maux de tête si nous devons changer ce type à un autre. Tout le monde gagne.
@Chris: J'ai dit que "la coulée du résultat de Malloc n'est pas requise dans c, mais est en C ++". Qui n'est pas discutable; C'est un fait, pas un avis. «Nécessaire» n'est pas une ordonnance sur ce qui est "juste", seulement sur ce qui est nécessaire.
J'ai dit "si vous avez besoin de compatibilité C ++, vous n'avez pas de choix." Je sais que c'est nécessaire en C ++, mais si nous utilisons c (dont la question est ambiguë), nous avons le choix, et cela devient donc une pratique discutable.
La vérification des valeurs de retour - en particulier les missions à l'aide du résultat du premier MALLOC.
Vous devez le faire séparément. D'abord allouer la structure, puis la mémoire des tableaux.
in c: p> en C ++, vous ne devriez pas faire quoi que ce soit comme ça. P> p>
Vous voulez utiliser Malloc pour allouer la mémoire et probablement également taille de () pour allouer la bonne quantité d'espace. P>
quelque chose comme: devrait faire le tour. p>
Structurevariable = (* SWC) MALLOC (Tailleof (SWC)); Code> P>
swc* a = malloc(sizeof(*a)); a->offset = calloc(n, sizeof(*(a->offset))); a->values = calloc(n, sizeof(*(a->values))); You should not cast void* in c... in c++ you must!
in c: in c ++: p> Notez qu'en C ++, vous pourriez être mieux à l'aide de vecteurs par opposition à Tampons alloués dynamiquement: p> struct swc
{
swc(size_t numOffset = SOME_DEFAULT_VALUE,
size_t numValues = SOME_OTHER_DEFAULT_VALUE)
{
m_offset = new short[numOffset];
m_values = new char[numValues];
}
~swc()
{
delete[] m_offset;
delete[] m_values;
}
short *m_offset;
char *m_values;
};
void foo(void)
{
swc *a = new swc(10,20); // m_offset and m_values allocated as
// part of the constructor
swc b; // uses default sizes for m_offset and m_values
...
a->m_offset[0] = 1;
a->m_values[0] = 'a';
b.m_offset[0] = 2;
b.m_values[0] = 'b';
...
delete a; // handles freeing m_offset and m_values
// b's members are deallocated when it goes out of scope
}
+1. C'est la seule réponse qui répond à sa question sur les valeurs d'exécution inconnues.
J'aimerais pouvoir +3 pour 1) différenciation entre C et C ++, 2) Vérification de la valeur de retour de MALLOC () code> et 3) à l'aide de
Tailleof var code> au lieu de
Tailleof (type) code>. Bien que au lieu d'un
std :: vecteur
std :: string code> moi-même.
Si vous allez utiliser des constructions C ++ comme des constructeurs et des destructeurs, veuillez le faire correctement. La définition ci-dessus est dangereuse. Vous DOOK B> Ajouter un constructeur de copie et un opérateur d'affectation ou trouver un autre moyen de gérer votre matrice de compensation et de valeurs. En outre, si vous voulez mettre en valeur des exceptions, vous devriez au moins montrer comment ranger la mémoire allouée (car elle n'est pas triviale avec deux pointeurs bruts)
Une chose à ajouter aux nombreuses réponses correctes ici: vous peut em> MALLOC code> une structure sur la taille supérieure pour accueillir un tableau de taille variable dans le dernier membre.
foo1->offsets = malloc(30*sizeof(short));
Oui! Vous l'avez admis: ça va créer un cauchemar de maintenance!
En plus de ce qui précède, je voudrais ajouter libérer la mémoire allouée comme ci-dessous.,
typedef struct { short *offset; char *values; } swc; swc* createStructure(int Count1, int Count2) { swc *s1 = new swc(); s1->offset = new short[Count1]; s1->values = new char[Count2]; return s1; } int _tmain(int argc, _TCHAR* argv[]) { swc *mystruct; mystruct = createStructure(11, 11); delete[] mystruct->offset; delete[] mystruct->values; delete mystruct; return 0; }
Ne mélangez pas et ne correspondez pas à C / C ++, ce sont des langues distinctes.
in c: in c ++ p>
IMHO ne jette pas la valeur de retour de MALLOC () code> in C. Si le type de
décalage code> passe de
court code> à
int < / code> (ou
long code> ou
long long code>) puis la coulée crée une autre ligne de code qui doit changer. Je préférerais faire
data-> offset = malloc (taille de données (* données-> décalage) * n) code>, qui fonctionnera toujours si le type de
décalage code> change.
Si Taille code> est zéro, alors
masloc code> peut valablement renvoyer
null code>, vous devez donc vérifier cela avant de décider que vous avez un objet partiellement créé ou Vous devriez ajouter "la taille est positif" comme condition préalable.
@Rob: vous êtes correct. J'avais supposé qu'un pointeur valide est retourné, mais lors de la lecture de la documentation, la mise en œuvre est définie en réalité (une autre raison de préférer C ++ nouveau).
La plupart des réponses sont correctes. Je voudrais ajouter quelque chose que vous n'avez pas explicitement demandé, mais peut également être important.
Les tableaux C / C ++ Disclaimer strong>: je me tromperais peut-être. Par exemple, si tout offset code> et
valeurs code> pour avoir des valeurs définies sur le temps de compilation (et, dans ce cas, il est préférable d'utiliser des tableaux de taille fixe), vous voudrez peut-être vouloir Stockez les tailles des deux tableaux dans le
struct code>. p>
décalse code> S de tous les code> SWC code> Les instances ont la même taille, il serait préférable de stocker
offset_count code> en tant que membre global, non En tant que membre du
struct code>. On peut dire que la même chose sur
valeurs code> et
valse_count code>. De plus, si
valeurs code> est une chaîne C, vous n'avez pas besoin de stocker sa taille, mais faites attention à Schlemiel le peintre problèmes de type. p> p>
N'utilisez pas int code> pour stocker des tailles. Vous ne voulez rien avoir à avoir une taille de -12, n'est-ce pas? Utilisez le type
Taille_t code> qui est créé pour stocker des tailles.
Puisque personne ne l'a déjà mentionné, il est parfois agréable de saisir cette pièce de mémoire dans une allocation de sorte que vous n'avez qu'à appeler gratuitement () sur une chose: bien sûr est un peu plus difficile à lire et à maintenir (surtout si vous redimensionnez de manière dynamique les tableaux après la première allouée). Juste une méthode alternative que j'ai vue utilisée dans plusieurs endroits. P> p>
1) Utilisez taille_t code> au lieu de
int code>. 2) La valeur hachée de ceci est incroyable (plus de 9000, peut-être). N'utilisez pas cela à moins que vous ayez trouvé que l'attribution est un goulot d'étranglement de la performance dans votre application et que vous avez constaté que cela facilite le goulot d'étranglement.
C'est nettement pas une bonne idée. Vous n'émettez pas de problèmes d'alignement de la mémoire. Si quelqu'un a décidé pour des raisons de maintenance de réorganiser les membres de la structure ou d'ajouter un autre membre, cela pourrait entraîner de vrais problèmes sur la route.
** si ** strong> Vous ne redimensionnerez pas les tableaux, vous pouvez vous éloigner avec un seul appel à MALLOC () CODE>.
swc *new_swc (int m, int n) {
swc *p;
p = malloc (sizeof (*p) + m * sizeof (p->offset[0]) + n * sizeof (p->values[0]);
p->offset = (short *) &p[1];
p->values = (char *) &p->offset[m];
return p;
}
Vous posez des questions sur C ou C ++? La meilleure solution va différer selon la langue que vous utilisez.
Bons exemples de la manière de l'allouer ci-dessous. Ce serait probablement une bonne idée de sauvegarder la taille des tableaux dans la structure pour le rendre plus général. Vous pouvez ensuite écraser des fonctions d'accès généralisées (en C) ou des méthodes d'accès membre (en C ++).
Échotant Neil: C et C ++ sont des langues très distinctes. Choisir un ou l'autre. N'utilisez pas d'hybride (comme indiqué dans beaucoup de réponses ci-dessous) Style qui est un mélange de langues.