
FAQ CConsultez toutes les FAQ
Nombre d'auteurs : 28, nombre de questions : 175, création le 11 janvier 2013
Sommaire→Les types et les variables→Structures et unions- Comment créer un alias pour le nom d'une structure ?
- Quelle est la différence entre une structure et une union ?
- Pourquoi la taille d'une structure n'est pas forcément égale à la somme des tailles de ses champs ?
- Comment copier une structure ?
- Comment comparer deux structures ?
- Que signifie 'unsigned int i : <n>;' ?
typedef struct {
int x;
int y;
} POINT2D;
Ou :
struct point2d_s {
int x;
int y;
};
typedef struct point2d_s POINT2D;
Ou encore:
typedef struct point2d_s {
int x;
int y;
} POINT2D;
Une structure est composée de différents champs qui ne se chevauchent pas.
#include <stdio.h>
struct point_s {
int x;
int y;
};
int main(void)
{
struct point_s A;
A.x = 1;
A.y = 2;
printf("A = (%d, %d)\n", A.x, A.y);
return 0;
}
Une union est composée de différents champs qui se superposent ou, en d'autres termes, qui utilisent le même emplacement mémoire. Il n'est donc tout simplement pas possible d'utiliser tous ces champs en même temps.
#include <stdio.h>
union duo_u {
int n;
double x;
};
int main(void)
{
union duo_u d;
d.n = 1;
/* Nous avons selectionne le champ n, nous devons utiliser ce champ */
/* et uniquement ce champ jusqu'a ce que nous n'en aurions plus besoin. */
printf("d.n = %d\n", d.n);
d.n = 2;
printf("d.n = %d\n", d.n);
d.x = 3.0;
/* Nous avons selectionne le champ x, nous devons utiliser ce champ */
/* et uniquement ce champ jusqu'a ce que nous n'en aurions plus besoin. */
printf("d.x = %f\n", d.x);
d.x = 4.0;
printf("d.x = %f\n", d.x);
return 0;
}
Comme nous pouvons le constater, les unions sont donc très pratiques pour économiser de la mémoire.
A cause des contraintes d'alignement imposées par certains processeurs. Certains processeurs imposent en effet qu'une donnée de type X doit se trouver en mémoire à une adresse respectant certains critères. Les champs d'une structure ne sont donc pas forcément adjacents !
En utilisant l'opérateur = ou la fonction memcpy (string.h).
#include <stdio.h>
#include <string.h>
struct personne_s {
char nom[21];
int age;
};
int main(void)
{
struct personne_s A, B, C;
strcpy(A.nom, "A");
A.age = 26;
B = A;
memcpy(&C, &A, sizeof(C));
printf("A.nom = %s\n", A.nom);
printf("A.age = %d\n", A.age);
printf("B.nom = %s\n", B.nom);
printf("B.age = %d\n", B.age);
printf("C.nom = %s\n", C.nom);
printf("C.age = %d\n", C.age);
return 0;
}
L'opérateur == n'étant pas défini pour les structures, il faut faire une comparaison champ par champ. On ne peut pas non plus utiliser la fonction memcmp car les champs d'une structure ne sont pas forcément adjacents comme les éléments d'un tableau par exemple. Les espaces créés entre les différents champs lorsqu'ils existent peuvent contenir des valeurs différentes même pour deux structures identiques or memcmp ne fait qu'une comparison bit par bit des contenus des mémoires comparées. Elle ne peut donc être utilisée pour comparer des structures.
Lien : Pourquoi la taille d'une structure n'est pas forcément égale à la somme des tailles de ses champs ?
'unsigned int i : <n>;' est une déclaration qui ne peut figurer que dans la définition d'une structure et qui permet de créer un champ, ici i, dont la taille est spécifiée en bits. i est ce qu'on appelle en langage C un champ de bits.
struct test_s
{
unsigned int i : 1;
unsigned int j : 2;
};
int main(void)
{
struct test_s s;
s.i = 0; /* A la fin de l'instruction, on aura s.i = 0 en binaire soit 0 en decimal. */
s.i++; /* A la fin de l'instruction, on aura s.i = 1 en binaire soit 1 en decimal. */
s.i++; /* A la fin de l'instruction, on aura s.i = 0 en binaire soit 0 en decimal. */
s.j = 0; /* A la fin de l'instruction, on aura s.j = 00 en binaire soit 0 en decimal. */
s.j++; /* A la fin de l'instruction, on aura s.j = 01 en binaire soit 1 en decimal. */
s.j++; /* A la fin de l'instruction, on aura s.j = 10 en binaire soit 2 en decimal. */
s.j++; /* A la fin de l'instruction, on aura s.j = 11 en binaire soit 3 en decimal. */
s.j++; /* A la fin de l'instruction, on aura s.j = 00 en binaire soit 0 en decimal. */
return 0;
}
Chaque implémentation doit au moins supporter les types int et unsigned int dans la déclaration d'un champ de bits. Une implémentation particulière peut toutefois supporter également d'autres types.



