Allouer dynamiquement de la structure C?
Je veux allouer dynamiquement une structure C:
typedef struct {
short *offset;
char *values;
} swc;
À la fois de "décalage" et des "valeurs" sont censés être des tableaux, mais leur taille est inconnue jusqu'à ce que l'exécution.
Comment puis-je allouer dynamiquement de la mémoire pour ma structure et la structure de tableaux?
Êtes-vous demander à propos de C ou C++? La meilleure solution sera différente en fonction de la langue que vous utilisez.
De bons exemples de la manière d'attribuer ce ci-dessous. Il serait probablement une bonne idée d'enregistrer la taille des matrices dans la structure pour la rendre plus générale. Vous pouvez ensuite écrit généralisée des fonctions d'accès (en C) ou membre de méthodes d'accès (en C++).
En écho à Neil: le C et le C++ sont très distinctes les langues. Choisir l'un ou l'autre. Ne pas utiliser un hybride (comme le montre beaucoup de réponses ci-dessous) de style qui est un mélange des deux langues.
De bons exemples de la manière d'attribuer ce ci-dessous. Il serait probablement une bonne idée d'enregistrer la taille des matrices dans la structure pour la rendre plus générale. Vous pouvez ensuite écrit généralisée des fonctions d'accès (en C) ou membre de méthodes d'accès (en C++).
En écho à Neil: le C et le C++ sont très distinctes les langues. Choisir l'un ou l'autre. Ne pas utiliser un hybride (comme le montre beaucoup de réponses ci-dessous) de style qui est un mélange des deux langues.
OriginalL'auteur pf. | 2009-12-30
Vous devez vous connecter pour publier un commentaire.
Où n = le nombre d'éléments de chaque tableau et un est l'adresse de la nouvellement allouée structure de données. N'oubliez pas de free() les compensations et les valeurs avant de free()'ing.
sizeof(char) peut toujours être un. Mais il est toujours agréable de l'avoir dans le code. C'sortes d'actes tels que les documents de ce que votre intention est (et ce n'est pas comme si il en coûte rien à l'exécution!).
Aussi en utilisant sizeof (*) et sizeof(a->valeurs[0]) signifie que vous ne répétez pas le type dans le code. Note sizeof est au moment de la compilation c'est sûr.
Tout d'abord, le casting de la valeur de retour de
malloc()
est une pratique incertaine, donc arrêter de faire comme si de votre choix à côté du débat, c'est le "bon". Il a été débattu de nombreuses fois, et ces observations sont pas de place à reproduire le débat. Si vous avez besoin de C++ de compatibilité, vous n'avez pas le choix, mais si vous ne le faites pas, je vous recommande de ne pas le faire, parce que si le type dea->offset
les modifications apportées à unlong
vous aurez à changer la fonte demalloc()
(et de touterealloc()
s vous pouvez également appeler) ou faire face à de graves bugs, ce qui conduit à plus d'entretien que nécessaire. (suite dans le prochain commentaire)Deuxièmement, pour la même raison, vous devez utiliser
sizeof(*a)
etsizeof(*a->offset)
au lieu desizeof(swc)
etsizeof(short)
. Si le type dea
changements (ou, plus probablement, le type dea->offset
changements deshort
àlong
), en utilisant la variable plutôt que le type vous permettra de changer seulement la ligne qui déclare la variable, plutôt que de changer toutes les lignes quimalloc()
etrealloc()
sur elle. Si ils sont tous d'en déduire le type de la variable (oustruct
membre), nous avons moins de maux de tête si nous devons changer ce type à un autre. Tout le monde y gagne.OriginalL'auteur spurserh
Dans C:
En C++:
Noter qu'en C++, vous pourriez être mieux à l'aide de vecteurs, par opposition à allouée dynamiquement tampons:
Question: est-valeurs censé être un tableau de caractères individuels ou un tableau de chaînes de caractères? Ça changerait un peu les choses.
MODIFIER
Plus j'y pense, le moins satisfait, je suis avec le C++ réponse; la droit façon de faire ce genre de chose en C++ (en supposant que vous besoin allouée dynamiquement les tampons en opposition à des vecteurs, dont vous n'avez probablement pas) est d'effectuer l'allocation de mémoire pour compenser et de valeurs dans le cadre d'un constructeur à l'intérieur de la structure de type, et ont un destructeur de libérer ces éléments lors de la struct instance est détruite (soit par un
delete
ou en allant hors de portée).Je souhaite que je pourrais +3 pour 1) la différenciation entre le C et le C++, 2) vérifier la valeur de retour de
malloc()
, et 3) à l'aide desizeof var
au lieu desizeof(type)
. Si, au lieu d'unstd::vector<char>
je pourrais juste aller de l'avant et utiliser unstd::string
moi-même.Si vous allez utiliser C++ constructions comme les constructeurs et les destructeurs, veuillez le faire correctement. La définition ci-dessus est dangereux. Vous ajouter un constructeur de copie et l'opérateur d'affectation ou de trouver une autre manière de gérer votre tableau de décalage et de valeurs. En plus si vous allez vers la vitrine des exceptions, alors vous devriez au moins montrer comment rattraper le mémoire qui a été allouée (comme il n'est pas trivial avec les deux PREMIÈRES pointeurs)
OriginalL'auteur John Bode
Vous devez le faire séparément. Allouer la structure, alors que la mémoire des tableaux.
Dans C:
En C++, vous ne devriez pas faire quoi que ce soit.
OriginalL'auteur Joe Gauterin
Dans C:
En C++
malloc()
en C. Si le type deoffset
changements deshort
àint
(oulong
oulong long
) puis coulée crée une ligne de code qui doit changer. Je préfère le fairedata->offset = malloc(sizeof(*data->offset) * n)
, qui peuvent encore fonctionner si le type deoffset
changements.Tous les bons points 🙂
Si
size
est zéro, alorsmalloc
peut valablement retourNULL
, je vous conseille donc de vérifier que, avant de décider que vous avez partiellement objet créé, ou vous devez ajouter "la taille est positif" comme une condition préalable.Vous êtes correct. J'avais supposé un pointeur valide est retourné, mais à la lecture de la documentation, il est effectivement mise en œuvre définies (une autre raison de préférer C++ nouveau).
OriginalL'auteur Martin York
Vous aurez besoin d'une fonction pour ce faire.
Quelque chose comme (mon C/C++ est rouillé)
Syntaxe peut être un peu, mais c'est généralement ce que vous allez avoir besoin. Si vous êtes à l'aide de C++, alors vous voudrez probablement une classe avec un constructeur prenant les 2 arguments au lieu de la makeStruct mais de faire quelque chose de très similaire.
Vous avez raison. Je suis gâté par java GC maintenant j'ai peur.
Si vous allez utiliser des constructions C++, alors vous devriez le faire tout le C++ voie et de le rendre constructeur/destructeur. Cet hybride C/C++ est contre-intuitif.
C++ dispose de sa propre beaucoup plus fine de la version de GC. Son appelé les pointeurs intelligents. L'embarras n'est pas le terme exact, je l'ai dit, paralysé 🙂 (Blague)
Ouais, j'ai utilisé des pointeurs intelligents un moment de retour. Ils ont presque fait de C++ dans un raisonnable langue à utiliser (bien que le code de base, j'ai été soutenir les mélanger avec la norme pointeurs - pure evil). Bien que, depuis le niveau de la question, je doute qu'elles sont un bon sujet pour ici.
OriginalL'auteur DaveC
Une chose à ajouter pour le nombre de bonnes réponses ici: vous peut
malloc
un cours de taille de structure pour accueillir un tableau de taille variable dans le dernier membre.et plus tard
pour obtenir de la place pour 30 objets dans le
values
tableau. Vous auriez encore besoin de fairesi vous souhaitez utiliser les mêmes matrices de taille.
En général, je ne le fait pas en fait (entretien cauchemar si la structure a jamais besoin de se développer), mais c'est un outil dans le kit.
[code ici dans c. Vous aurez besoin de lancer le
malloc
(ou de mieux utilisernew
RAII et locutions) en c++]J'ai, néanmoins, vu qu'il fait.
OriginalL'auteur dmckee
Vous ne devraient pas jeter un void* en c... en c++ vous devez!
OriginalL'auteur warp
Utiliser la fonction de malloc ou calloc pour allouer de la mémoire dynamiquement .
et il recherche sur google pour obtenir des exemples.
Sans doute encore la peine de mentionner new/delete sont des constructions C++. D'autant que les structures ne sont pas courants dans le C++ monde.
oui je le sais et je suis supprimant nouveau/supprimer une partie de la réponse.
OriginalL'auteur Ashish
Puisque personne n'a parlé encore, parfois il est agréable de saisir cette partie de la mémoire dans l'une allocation de sorte que vous n'avez qu'à appeler free() sur une chose:
Bien sûr, c'est un peu plus difficile à lire et à maintenir (surtout si vous redimensionner dynamiquement les tableaux après il est d'abord affecté). Juste une méthode alternative je l'ai vu utilisé dans un certain nombre de lieux.
size_t
au lieu deint
. 2) Le hack de la valeur de ce qui est incroyable (plus de 9000, peut-être). Ne pas l'utiliser, sauf si vous avez trouvé que l'allocation est un goulot d'étranglement des performances de votre application et que vous avez trouvé que cela facilite le goulot d'étranglementCe n'est certainement pas une bonne idée. Vous n'envisagez pas de mémoire problèmes d'alignement. Si quelqu'un a décidé pour des raisons de maintenance pour réorganiser les membres de la structure ou ajouter un autre membre, cela pourrait conduire à des problèmes réels en bas de la route.
OriginalL'auteur Luke
La plupart des réponses sont correctes. Je voudrais ajouter quelque chose que vous n'avez pas explicitement demandé, mais peut également être important.
C /C++ tableaux ne pas stocker leur taille en mémoire. Donc, sauf si vous voulez
offset
etvalues
avoir au moment de la compilation les valeurs définies (et, dans ce cas, il est préférable d'utiliser de taille fixe tableaux), vous pourriez vouloir stocker les tailles des deux tableaux dans lestruct
.AVERTISSEMENT: j'ai peut-être tort. Par exemple, si tous les
offset
s de tous lesswc
instances ont la même taille, il serait préférable de les stockeroffset_count
mondiale en tant que membre, et non en tant que membre de lastruct
. La même chose peut être dit à propos devalues
etvalues_count
. Aussi, sivalues
est une chaîne C, vous n'avez pas besoin de stocker sa taille, mais méfiez-vous de Schlemiel le peintreproblèmes similaires.int
à la taille des banques. Vous ne voulez pas n'importe quoi pour avoir une taille de 12 ans, avez-vous? Utilisez le typesize_t
qui est créé pour stocker les tailles.Oui, vous avez raison. Mon mauvais.
OriginalL'auteur pyon
Vous souhaitez utiliser malloc pour allouer de la mémoire, et probablement aussi sizeof() pour allouer le montant correct de l'espace.
Quelque chose comme:
structVariable = (*swc) malloc(sizeof(swc));
Devrait faire l'affaire.
OriginalL'auteur Adam Luchjenbroers
En plus de ce qui précède, je voudrais ajouter de libérer la mémoire allouée comme ci-dessous.,
OriginalL'auteur Red
**Si** vous ne serez pas le redimensionnement des tableaux, alors vous pouvez vous en sortir avec un seul appel à
malloc()
.Vous pouvez ensuite gratuitement avec un seul appel à
free()
.(En général, il y a l'alignement des éléments à prendre en compte, mais pour une série de courts-métrages suivie par un tableau de caractères, vous serez amende.)
OriginalL'auteur dave4420