2016-10-08 1 views
0

À chaque fois que des structures sont lancées à l'intérieur d'autres structures, je suis confus pour une raison quelconque. J'écris un pilote pour un I2C (Interface Serial 2 fils) et j'utilise les pilotes du fabricant comme référence pour créer le mien. J'ai cette déclaration d'union ci-dessous (qui est définie dans un fichier d'en-tête) et je ne peux pas comprendre quelques lignes à l'intérieur. Juste un bref historique afin que vous sachiez ce que vous regardez est l'extrait principal ci-dessous est mise en place de cette variable TWI_statusReg qui détient les informations d'un registre d'état chaque fois que je transmets/réception de données sur le bus I2C. Ce registre de données fait 8 bits et appartient à un microcontrôleur Atmel Atmega328P. Voici mes questions ...Structure de données à l'intérieur d'une Union (Programmation C)

1.) Il est difficile de formuler cette question en mots, mais pouvez-vous expliquer en termes simples pourquoi vous déclareriez une structure de données dans une structure comme celle-ci? Quels points clés devrais-je choisir?

2.) Dans le fichier de définition d'en-tête « .c » qui est trop long pour poster ici, il y a une seule ligne qui dit le texte suivant

TWI_statusReg.all = 0; 

Je sais qu'il ya une variable char dans l'en-tête fichier appelé "tout" comme vu dans l'extrait principal de code ci-dessous. Cependant, je ne comprends pas ce qui se passe quand on lui attribue un zéro. Est-ce que tous les bits du registre d'état sont mis à zéro?

3.) Les deux lignes

unsigned char lastTransOK:1; 
unsigned char unusedBits:7; 

sont source de confusion pour moi précisément ce que l'opérateur du côlon fait.

L'extrait principal de CODE

/**************************************************************************** 
    Global definitions 
****************************************************************************/ 

union TWI_statusReg      // Status byte holding flags. 
{ 
    unsigned char all; 
    struct 
    { 
     unsigned char lastTransOK:1;  
     unsigned char unusedBits:7; 
    }; 
}; 

extern union TWI_statusReg TWI_statusReg; 
+0

L'opérateur deux-points spécifie le nombre de bits utilisés pour ce champ. –

+0

Et les champs de bits sont non portables. Il n'y a pas de moyen indépendant de la plate-forme que je connaisse pour savoir quel bit de 'all' correspond au bit' lastTansOK'. Ce pourrait être le premier bit, ou ce pourrait être le dernier morceau. Et si vous utilisez un compilateur différent, il est susceptible de changer.Si –

+2

'TWI_statusReg.all = 0;' est dans un fichier d'en-tête (en dehors d'une fonction 'inline' ou une macro, il jette une très mauvaise lumière sur la qualité du code Votre question est confus et peu clair Le mieux est d'obtenir un C.. . livre et lire les sections sur '' struct's et – Olaf

Répondre

0

1) La principale raison d'écrire une telle union est la commodité. Au lieu de faire manuellement des masques de bits chaque fois que vous avez besoin d'accéder à des bits spécifiques, vous avez maintenant des alias pour ces bits.

2) Les unions vous permettent de vous référer à la mémoire comme si ses composants étaient des variables différentes représentant différents types. Les syndicats n'allouent de l'espace que pour le plus grand composant à l'intérieur d'eux. Donc, si vous avez

union Example { 
     char bytes[3]; 
     uint32_t num; 
}; 

une telle union prendrait 4 octets, depuis son plus grand de type uint32_t prend 4 octets d'espace. Il serait probablement plus logique d'avoir une union comme celui-ci cependant, puisque vous utilisez cet espace de toute façon et il est plus pratique:

union Example { 
     char bytes[4]; 
     uint32_t num; 
}; 

octets tableau vous permet d'accéder octets individuels de num.

Votre estimation est correcte - la valeur d'écriture pour tous définira les bits correspondants de l'union.

3) Cette construction est appelée bit field, et est une optimisation de l'utilisation de la mémoire - si vous utilisiez une structure de 2 caractères, cela prendrait en fait 2 octets d'espace mémoire, mais si vous déclarez un champ de bits, ne prend que 1 octet (et vous avez encore 6 autres bits "inutilisés")