Différence entre une structure et une union

Y a-t-il un bon exemple pour faire la différence entre une struct et une union ? Fondamentalement, je sais que struct utilise toute la mémoire de son membre et que union utilise l’espace mémoire le plus grand des membres. Y a-t-il une autre différence au niveau du système d’exploitation?

Avec une union, vous êtes seulement censé utiliser l’un des éléments, car ils sont tous stockés au même endroit. Cela le rend utile lorsque vous souhaitez stocker quelque chose qui pourrait être de plusieurs types. Une structure, quant à elle, possède un emplacement de mémoire distinct pour chacun de ses éléments et tous peuvent être utilisés simultanément.

Pour donner un exemple concret de leur utilisation, je travaillais sur un interpréteur Scheme il y a peu de temps et je recouvrais essentiellement les types de données Scheme sur les types de données C. Cela impliquait de stocker dans une structure une énumération indiquant le type de valeur et une union pour stocker cette valeur.

 union foo { int a; // can't use both a and b at once char b; } foo; struct bar { int a; // can use both a and b simultaneously char b; } bar; union foo x; xa = 3; // OK xb = 'c'; // NO! this affects the value of xa! struct bar y; ya = 3; // OK yb = 'c'; // OK 

edit: Si vous vous demandez quel réglage de xb sur ‘c’ change la valeur de xa, techniquement parlant, c’est indéfini. Sur la plupart des machines modernes, un caractère est de 1 octet et l’int est de 4 octets, donc donner la valeur ‘c’ à xb donne également le premier octet de la même valeur:

 union foo x; xa = 3; xb = 'c'; printf("%i, %i\n", xa, xb); 

estampes

 99, 99 

Pourquoi les deux valeurs sont-elles les mêmes? Parce que les 3 derniers octets de l’int 3 sont tous nuls, il est donc aussi lu comme 99. Si nous mettons un plus grand nombre pour xa, vous verrez que ce n’est pas toujours le cas:

 union foo x; xa = 387439; xb = 'c'; printf("%i, %i\n", xa, xb); 

estampes

 387427, 99 

Pour examiner de plus près les valeurs de mémoire réelles, définissons et imprimons les valeurs en hexadécimal:

 union foo x; xa = 0xDEADBEEF; xb = 0x22; printf("%x, %x\n", xa, xb); 

estampes

 deadbe22, 22 

Vous pouvez voir clairement où le 0x22 a remplacé le 0xEF.

MAIS

En C, l’ordre des octets dans un int n’est pas défini. Ce programme a remplacé le 0xEF avec 0x22 sur mon Mac, mais il existe d’autres plates-formes où il écraserait plutôt le 0xDE parce que l’ordre des octets qui composent l’int int a été inversé. Par conséquent, lors de l’écriture d’un programme, vous ne devez jamais vous fier au comportement de remplacement de données spécifiques dans une union car ce n’est pas portable.

Pour plus de lecture sur le classement des octets, vérifiez l’ endianness .

Voici la réponse courte: une structure est une structure d’enregistrement: chaque élément de la structure alloue de nouveaux espaces. Donc, une structure comme

 struct foobarbazquux_t { int foo; long bar; double baz; long double quux; } 

alloue au moins (sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double)) octets en mémoire pour chaque instance. (“Au moins” car les contraintes d’alignement de l’architecture peuvent forcer le compilateur à remplir la structure.)

D’autre part,

 union foobarbazquux_u { int foo; long bar; double baz; long double quux; } 

alloue un morceau de mémoire et lui donne quatre alias. So sizeof(union foobarbazquux_u) ≥ max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double)) , avec la possibilité d’append des alignements.

Existe-t-il un bon exemple pour faire la différence entre une «structure» et une «union»?

Un protocole de communication imaginaire

 struct packetheader { int sourceaddress; int destaddress; int messagetype; union request { char fourcc[4]; int requestnumber; }; }; 

Dans ce protocole imaginaire, il a été spécifié que, sur la base du “type de message”, l’emplacement suivant dans l’en-tête sera soit un numéro de requête, soit un code de quatre caractères, mais pas les deux. En résumé, les unions permettent à un même emplacement de stockage de représenter plusieurs types de données, où il est garanti que vous ne souhaitez stocker qu’un des types de données à la fois.

Les unions sont en grande partie un détail de bas niveau basé sur l’inheritance de C en tant que langage de programmation système, où des emplacements de stockage “se chevauchant” sont parfois utilisés de cette manière. Vous pouvez parfois utiliser des unions pour économiser de la mémoire lorsque vous avez une structure de données où un seul parmi plusieurs types sera enregistré à la fois.

En général, le système d’exploitation ne se soucie pas des structs et des unions – il s’agit simplement de blocs de mémoire. Une structure est un bloc de mémoire qui stocke plusieurs objects de données, où ces objects ne se chevauchent pas. Une union est un bloc de mémoire qui stocke plusieurs objects de données, mais ne contient que le plus grand d’entre eux, et ne peut donc stocker qu’un des objects de données à la fois.

Comme vous le dites déjà dans votre question, la principale différence entre l’ union et la struct est que union membres d’ union superposent la mémoire l’un de l’autre, de sorte que la taille d’union est la même. entre). De plus, un syndicat est suffisamment grand pour contenir tous ses membres et a un alignement qui convient à tous ses membres. Alors, disons que int ne peut être stocké qu’à des adresses de 2 octets et qu’il est large de 2 octets, et que long ne peut être stocké qu’à des adresses de 4 octets et qu’il a 4 octets de long. L’union suivante

 union test { int a; long b; }; 

pourrait avoir une sizeof de 4, et une exigence d’alignement de 4. Une union et une structure peuvent avoir un remplissage à la fin, mais pas au début. L’écriture dans une structure modifie uniquement la valeur du membre écrit. Écrire à un membre d’un syndicat rend la valeur de tous les autres membres invalide. Vous ne pouvez pas y accéder si vous ne leur avez pas écrit auparavant, sinon le comportement n’est pas défini. GCC fournit une extension que vous pouvez réellement lire des membres d’un syndicat, même si vous ne leur avez pas écrit récemment. Pour un système d’exploitation, il n’est pas nécessaire que le programme utilisateur écrive dans une union ou une structure. Ce n’est en fait qu’un problème du compilateur.

Une autre propriété importante de l’union et de la structure est qu’elle permet à un pointeur vers eux de pointer vers des types de ses membres . Donc, ce qui suit est valide:

 struct test { int a; double b; } * some_test_pointer; 

some_test_pointer peut pointer sur int* ou bool* . Si vous convertissez une adresse de type test en int* , cela désignera en fait son premier membre, a . La même chose est vraie pour un syndicat aussi. Ainsi, une union ayant toujours le bon alignement, vous pouvez utiliser une union pour que le pointage vers un type soit valide:

 union a { int a; double b; }; 

Cette union pourra effectivement pointer vers un int et un double:

 union a * v = (union a*)some_int_pointer; *some_int_pointer = 5; v->a = 10; return *some_int_pointer; 

est en fait valide, comme indiqué par la norme C99:

Un object ne doit avoir sa valeur stockée que par une expression lvalue ayant l’un des types suivants:

  • un type compatible avec le type effectif de l’object
  • un type d’agrégat ou d’union qui inclut l’un des types susmentionnés parmi ses membres

Le compilateur n’optimisera pas le v->a = 10; car cela pourrait affecter la valeur de *some_int_pointer (et la fonction retournera 10 au lieu de 5 ).

Une union est utile dans quelques scénarios. union peut être un outil de manipulation de très bas niveau, comme l’écriture de pilotes de périphériques pour un kernel.

Un exemple de ceci est la dissection d’un nombre float en utilisant l’ union d’une struct avec des champs de bits et un float . J’enregistre un nombre dans le float et plus tard, je peux accéder à certaines parties du float via cette struct . L’exemple montre comment l’ union est utilisée pour avoir des angles différents pour examiner les données.

 #include  union foo { struct float_guts { unsigned int fraction : 23; unsigned int exponent : 8; unsigned int sign : 1; } fg; float f; }; void print_float(float f) { union foo ff; ff.f = f; printf("%f: %d 0x%X 0x%X\n", f, ff.fg.sign, ff.fg.exponent, ff.fg.fraction); } int main(){ print_float(0.15625); return 0; } 

Jetez un oeil à la description de précision unique sur wikipedia. J’ai utilisé l’exemple et le numéro magique 0.15625 de là.


union peut également être utilisée pour implémenter un type de données algébrique comportant plusieurs alternatives. J’en ai trouvé un exemple dans le livre “Real World Haskell” de O’Sullivan, Stewart et Goerzen. Vérifiez-le dans la section Union discriminée .

À votre santé!

union ” et ” struct ” sont des constructions du langage C. Parler d’une différence “au niveau du système d’exploitation” entre eux est inapproprié, car c’est le compilateur qui produit un code différent si vous utilisez un mot-clé ou un autre.

Non techniquement parlant signifie:

Hypothèse: chaise = bloc mémoire, personnes = variable

Structure : S’il y a 3 personnes, elles peuvent s’asseoir de la même taille.

Union : S’il y a 3 personnes qu’une seule chaise sera là pour s’asseoir, toutes devront utiliser la même chaise lorsqu’elles veulent s’asseoir.

Techniquement parlant signifie:

Le programme mentionné ci-dessous donne une profonde plongée dans la structure et l’union.

 struct MAIN_STRUCT { UINT64 bufferaddr; union { UINT32 data; struct INNER_STRUCT{ UINT16 length; UINT8 cso; UINT8 cmd; } flags; } data1; }; 

Taille totale MAIN_STRUCT = sizeof (UINT64) pour bufferaddr + sizeof (UNIT32) pour union + 32 bits pour le remplissage (dépend de l’architecture du processeur) = 128 bits. Pour la structure, tous les membres obtiennent le bloc de mémoire contigu.

Union obtient un bloc de mémoire du membre de taille maximale (ici son bit 32). Dans l’union, une structure supplémentaire se trouve (INNER_STRUCT), ses membres obtiennent un bloc mémoire de taille totale 32 bits (16 + 8 + 8). Dans l’union, vous pouvez accéder au membre INNER_STRUCT (32 bits) ou aux données (32 bits).

Oui, la principale différence entre struct et union est la même que celle que vous avez énoncée. Struct utilise toute la mémoire de son membre et l’union utilise le plus grand espace mémoire des membres.

Mais toute la différence réside dans le besoin d’utilisation de la mémoire. Le meilleur usage de l’union peut être vu dans les processus d’Unix où nous utilisons des signaux. comme un processus ne peut agir que sur un seul signal à la fois. Donc, la déclaration générale sera:

 union SIGSELECT { SIGNAL_1 signal1; SIGNAL_2 signal2; ..... }; 

Dans ce cas, le processus n’utilise que la mémoire la plus élevée de tous les signaux. mais si vous utilisez struct dans ce cas, l’utilisation de la mémoire sera la sum de tous les signaux. Fait beaucoup de différence.

Pour résumer, Union doit être sélectionné si vous savez que vous accédez à l’un des membres à la fois.

Une structure alloue la taille totale de tous les éléments qu’elle contient.

Une union n’alloue que la quantité de mémoire requirejse par son membre le plus important.

Vous l’avez, c’est tout. Mais en gros, quel est le but des syndicats?

Vous pouvez mettre dans le même emplacement le contenu de différents types. Vous devez connaître le type de ce que vous avez stocké dans l’union (si souvent vous le mettez dans une struct avec une balise de type …).

Pourquoi est-ce important? Pas vraiment pour des gains d’espace. Oui, vous pouvez gagner quelques bits ou faire un peu de remplissage, mais ce n’est plus le point principal.

C’est pour la sécurité des types, cela vous permet de faire une sorte de “typage dynamic”: le compilateur sait que votre contenu peut avoir différentes significations et la signification précise de votre interprétation au moment de l’exécution. Si vous avez un pointeur qui peut pointer vers différents types, vous DEVEZ utiliser une union, sinon votre code peut être incorrect en raison de problèmes d’alias (le compilateur se dit “oh, seul ce pointeur peut pointer vers ce type, donc je peux optimiser sur ces access … “, et de mauvaises choses peuvent arriver.

Les utilisations des unions Unions sont fréquemment utilisées lorsque des conversations de type spécialisé sont nécessaires. Pour avoir une idée de l’utilité de l’union. La bibliothèque standard c / c ne définit aucune fonction spécifiquement conçue pour écrire des entiers courts dans un fichier. L’utilisation de fwrite () entraîne une surcharge excessive pour une opération simple. Cependant, en utilisant une union, vous pouvez facilement créer une fonction qui écrit des binarys d’un entier court dans un fichier un octet à la fois. Je suppose que les entiers courts ont 2 octets de long

L’EXEMPLE:

 #include union pw { short int i; char ch[2]; }; int putw(short int num, FILE *fp); int main (void) { FILE *fp; fp fopen("test.tmp", "wb "); putw(1000, fp); /* write the value 1000 as an integer*/ fclose(fp); return 0; } int putw(short int num, FILE *fp) { pw word; word.i = num; putc(word.c[0] , fp); return putc(word.c[1] , fp); } 

bien que putw () j’ai appelé avec un entier court, il était possible d’utiliser putc () et fwrite (). Mais je voulais montrer un exemple pour montrer comment une union peut être utilisée

la structure est une collection de différents types de données où différents types de données peuvent résider et que chacun reçoit son propre bloc de mémoire

nous avons généralement utilisé l’union lorsque nous sums sûrs qu’une seule variable sera utilisée à la fois et que vous voulez utiliser pleinement la mémoire actuelle car elle n’obtient qu’un seul bloc de mémoire égal au plus grand.

 struct emp { char x;//1 byte float y; //4 byte } e; 

Mémoire totale obtenue => 5 octets

 union emp { char x;//1 byte float y; //4 byte } e; 

Mémoire totale obtenue = 4 octets

Quelle est la différence entre structure et union?

La réponse courte est la suivante: la déférence est dans l’allocation de mémoire. Explication: Dans la structure, un espace mémoire sera créé pour tous les membres de la structure. Dans l’union, l’espace mémoire sera créé uniquement pour un membre ayant besoin d’un espace mémoire plus important. Considérez le code suivant:

 struct s_tag { int a; long int b; } x; union u_tag { int a; long int b; } y; 

Ici, il y a deux membres dans struct et union: int et long int. L’espace mémoire pour int est de: 4 octets et l’espace mémoire pour long int est: système d’exploitation 8 en 32 bits.

Donc pour struct 4 + 8 = 12 octets seront créés alors que 8 octets seront créés pour l’union

Exemple de code:

 #include struct s_tag { int a; long int b; } x; union u_tag { int a; long int b; } y; int main() { printf("Memory allocation for structure = %d", sizeof(x)); printf("\nMemory allocation for union = %d", sizeof(y)); return 0; } 

Réf: http://www.codingpractise.com/home/c-programming/structure-and-union/

Les syndicats sont utiles lors de l’écriture d’une fonction de classement des octets, donnée ci-dessous. Ce n’est pas possible avec les structures.

 int main(int argc, char **argv) { union { short s; char c[sizeof(short)]; } un; un.s = 0x0102; if (sizeof(short) == 2) { if (un.c[0] == 1 && un.c[1] == 2) printf("big-endian\n"); else if (un.c[0] == 2 && un.c[1] == 1) printf("little-endian\n"); else printf("unknown\n"); } else printf("sizeof(short) = %d\n", sizeof(short)); exit(0); } // Program from Unix Network Programming Vol. 1 by Stevens. 

Une Union est différente d’une structure car une Union se répète sur les autres: elle redéfinit la même mémoire alors que la structure se définit les unes après les autres sans chevauchement ni redéfinition.