Unions versus structures en C
L'idée derrière cette question est de comprendre la plus profonde des concepts de l'aide de l'union et de l'utiliser de manière différente afin d'économiser de la mémoire.. Ma question est--
disons qu'il s'agit d'une structure
struct strt
{
float f;
char c;
int a;
}
et la même structure représentée dans l'union
union unin
{
float f;
char c;
int a;
}
Si j'affecter des valeurs à la structure des membres l'un après l'autre et de les imprimer ensuite, il obtient
imprimée. Mais dans le cas de l'union, il n'arrive pas, pour certains d'écrasement est fait..
J'ai donc besoin de trouver une méthode qui peut stocker les valeurs de f,c,a, à l'aide de l'union et que je peux ensuite imprimer le même. (Appliquer toutes les opérations ou quoi que ce soit..) mais je suis à la recherche de cette technique.. quelqu'un Peut-il là me guider ou me donner une idée?
source d'informationauteur AGeek
Vous devez vous connecter pour publier un commentaire.
Si vous regardez la façon dont une structure stocke ses valeurs, il serait quelque chose comme ceci:
Ainsi, lorsque vous modifiez la valeur de f, vous êtes en train de changer octets 0-3. Lorsque vous modifiez votre char, vous changez en fait 4 octets. Lorsque vous modifiez votre int, vous êtes en train de modifier les octets 5 à 8.
Si vous regardez maintenant comment une union stocke ses valeurs, il serait quelque chose comme ceci:
Alors maintenant, quand je change la valeur de f, je suis l'évolution octets 0-3. Depuis c est stockée dans l'octet 0, lorsque vous modifiez f, vous modifiez également les c et une! Lorsque vous modifiez c, vous passez d'une partie de f et a - et lorsque l'on change, vous changez c) et f). C'est là que votre "écraser" qui se passe. Lorsque vous pack les 3 valeurs dans une adresse mémoire, vous n'êtes pas "économiser de l'espace" à tous; vous êtes tout simplement la création de 3 différentes façons de voir et de changer les mêmes données. Vous n'avez pas vraiment un int, un float, et un char dans l'union - au niveau physique, vous avez juste obtenu de 32 bits, ce qui peut être considéré comme un int, un float ou un char. Le changement de l'un est signifiait de changer les autres. Si vous n'en voulez pas à changer les uns des autres, puis d'utiliser un struct.
C'est pourquoi gcc vous dit que votre structure est de 9 octets de long, tandis que votre union est à seulement 4 - il n'est pas de gagner de l'espace - c'est juste que les structures et les syndicats ne sont pas la même chose.
Je pense que vous ne comprenez pas le but d'un
union
.Un
union
comme son nom l'indique, définit une structure où l'ensemble de ses membres occupent le même espace mémoire. Alors qu'unstruct
lieux de chacun de ses membres, de mémoire distincts en une seule zone contiguë.Avec votre union, lorsque vous écrivez:
Puis
foo.a
etfoo.f
permettra à la fois d'être changé. C'est parce que.a
.c
et.f
sont stockées dans le même emplacement de mémoire. Ainsi, chaque membre d'un syndicat est une autre "vue" de la même mémoire. Cela n'arrive pas avec unstruct
parce que tous les membres sont distincts et séparés les uns des autres.Il n'y a pas moyen de contourner ce problème parce que c'est intentionnel.
Je pense que vous êtes malentendu Syndicats.
oui, c'est une des raisons
pas
il n'est pas équivalent. Ils ont l'air similaire dans le code source, mais c'est une chose complètement différente. Comme les pommes et les avions.
Les syndicats sont une très, très faible niveau de construction qui vous permet de voir un morceau de la mémoire comme si le stockage d'un de ses "membres", mais vous ne pouvez utiliser un à un. Même l'utilisation du mot "membre" est extrêmement trompeur. Ils devraient être appelés "points de vue", ou quelque chose, non membres.
Lorsque vous écrivez:
Vous en disant: "prenez un morceau de mémoire assez grande pour le plus grand entre un int, un char et un double, et permet de l'appeler myAbc.
Dans ce mémoire, maintenant, vous pouvez stocker soit un int, ou un double, ou un char. Si vous stockez un int, puis de conserver un double, l'int est allé pour toujours.
Quel est l'intérêt alors?
Il y a deux utilisations principales pour les Syndicats.
a) Victimes de stockage
C'est ce que nous avons fait ci-dessus. - Je récupérer un morceau de la mémoire et je donne des significations différentes selon le contexte. Parfois, le contexte est explicite (on en garde une partie variable qui indique ce "genre" de la variable que vous avez stockées), et parfois, il peut être implicite (en fonction de la section de code, vous pouvez dire que l'on doit être en cours d'utilisation). De toute façon, le code doit être en mesure de le comprendre, ou vous ne serez pas en mesure de faire quelque chose de sensé avec la variable.
Un type (explicite) exemple serait:
Par exemple, VB6 "Variantes" sont les Syndicats ne sont pas, contrairement à ce qui précède (mais plus complexe).
b) Diviser la représentation
C'est parfois utile lorsque vous avez besoin pour être en mesure de voir une variable comme un "ensemble" ou d'une combinaison de pièces. Il est plus facile à expliquer avec un exemple:
Voici un short int "fusionné" avec une paire d'octets. Maintenant, vous pouvez afficher la même valeur qu'un short int (myVar.Entier), ou vous pouvez tout aussi facile d'étudier les octets individuels qui font partie de la valeur (myVar.octets.un et myVar.octets.b).
Noter que cette deuxième utilisation n'est pas portable (je suis sûr); ce qui signifie qu'il n'est pas garanti à travailler dans différents types d'architectures de machines; mais cet usage est absolument essentiel pour ce type de tâches pour lesquelles C a été conçu (OS de la mise en œuvre).
Une union contient un ensemble de mutuellement exclusifs de données.
Dans votre exemple, vous pouvez stocker le flotteur (f), char (c) ou int (un) dans l'union. Toutefois, la mémoire ne seront alloués pour la plus grand élément dans l'union. Tous les éléments de l'union partagent la même partie de la mémoire. En d'autres mots, l'écriture d'une valeur dans l'union suivie par une autre, sera la cause de la première valeur qui doit être remplacé.
Vous avez besoin de revenir en arrière et posez-vous ce que vous êtes à la modélisation:
Voulez-vous vraiment les valeurs de fc et un mutuellement exclusifs (c'est à dire une seule valeur peut exister à la fois)? Si oui, envisagez l'utilisation d'un syndicat en conjonction avec une valeur d'enum (stockées en dehors de l'union) qui indique quel membre de l'union est "active" à n'importe quel point dans le temps. Cela vous permettra d'obtenir la mémoire des avantages de l'utilisation d'un syndicat, au prix de plus de code dangereux (comme quelqu'un maintien devront être conscients du fait que les valeurs sont mutuellement exclusives, c'est à dire qu'il est, en effet, une union). Seulement envisager cette option si vous êtes à la création d'un grand nombre de ces syndicats et de la mémoire de conservation est indispensable (par exemple, sur les Processeurs). Vous ne pouvez PAS même à une économie de mémoire, car vous aurez besoin pour créer enum variables sur la pile, ce qui va prendre de la mémoire aussi.
Voulez-vous ces valeurs pour être à la fois active et de ne pas interférer les uns avec les autres? Si oui, vous aurez besoin d'utiliser une structure de la place (que vous mettez dans votre premier exemple). Cela permettra d'utiliser plus de mémoire lorsque vous instanciez un struct, la mémoire est allouée est la somme de tous les membres (plus de rembourrage pour le plus proche de la limite de mot). À moins que la mémoire de conservation est d'une importance capitale (voir exemple précédent), je serais favorable à cette approche.
Edit:
(Très simple) exemple de comment utiliser les énumérations en conjonction avec un syndicat:
C'est un exemple classique de l'utilisation d'une union pour stocker des données selon un marqueur externe.
L'int, float et char * tous les occupent la même place dans l'union, ils ne sont pas consécutifs donc, si vous avez besoin pour stocker tous, c'est une structure que vous êtes à la recherche pour, non à un syndicat.
La structure est la taille du plus grand chose dans l'union, plus la taille du type, car il est à l'extérieur de l'union.
La printMyType fonction de détecter correctement ce qui est stocké dans la structure (à moins de se mentir à elle) et d'imprimer la valeur correspondante.
Lorsque vous remplissez l'un d'eux, vous avez à faire:
ou
et un
x
ne peut être qu'une chose à la fois.Malheur à quiconque tente:
Ils demandent à ce que des ennuis.
Les syndicats sont généralement utilisés lorsque seulement l'un des ci-dessous devraient être stockées dans une instance à tout moment. c'est à dire que vous pouvez stocker un float, un char ou un int à tout instant. C'est pour économiser de la mémoire - par la non-allocation supplémentaire/distinct de la mémoire pour un float et un int, quand vous allez l'utiliser pour stocker un char. La quantité de mémoire allouée = plus grand type dans l'union.
L'autre usage de l'union, c'est quand vous voulez stocker quelque chose qui a de pièces, laissez-sat il est possible de modéliser un registre en tant qu'union contenant de l'upper byte, octet de poids faible et une valeur composite. Ainsi, vous pouvez stocker une valeur composite dans l'union et d'utiliser les membres pour obtenir les éléments par les autres membres.