2010-06-21 7 views
9

Les champs de bits peuvent-ils être utilisés en union?c union et champs de bits

+12

Quand vous faites deux choses mauvaises, ont-ils la somme ou de multiplier? ;-) –

+0

+1 à Amardeep. Ne pas et ne pas divya. –

+0

Les champs de bits négatifs et les unions ne doivent pas être mauvais. J'utilise des structures dans les syndicats pour analyser les octets d'entrée/sortie dans un logiciel embarqué. Son confort surpasse ses inconvénients. – schmijos

Répondre

2

Oui c'est possible, mais je le déconseille. La longueur et l'emballage des champs de bits ne sont pas portables. La taille de l'union sera difficile à prévoir (voir here). Il y a une certaine quantité de complexité que vous introduisez dans le code lorsque vous utilisez des unions ou des champs de bits. Bien que cette complexité puisse être acceptable dans votre code, la combinaison des deux peut entraîner une complexité inacceptable. Si vous utilisez des unions, des structures et des champs de bits, vous rencontrez des problèmes d'alignement de la mémoire.

S'il s'agit d'un code jetable qui doit seulement être construit et exécuté sur une machine, alors c'est probablement bien. Cependant, si vous vérifiez cela dans le contrôle de version où il vivra éternellement, je recommande contre cela.

Si vous donnez un exemple de pourquoi vous voulez faire cela, moi ou quelqu'un d'autre peut suggérer une meilleure alternative.

EDIT: clarifié sur la base de commentaires et de demander des commentaires.

+3

Qu'est-ce qui n'est pas portable sur les bits-fields dans les unions par rapport aux bits-fields en général? Qu'est-ce qui va être difficile à prédire? – AnT

+3

La plainte dans le poste que vous avez lié était sur le sizeof() une union contenant un bitfield, pas le comportement. La taille de la structure dépend toujours de l'implémentation et cela n'a rien à voir avec le champ de bits. Il y avait aussi une plainte pour ne pas avoir pu prendre l'adresse d'un membre de bitfield, mais c'est juste comme ça que ça fonctionne et ça n'a rien à voir avec le syndicat. – Alan

+0

Mis à jour pour être moins vague. En général, je suis hyperparanoïde sur la taille/alignement de la mémoire parce que je travaille sur le firmware pour les microcontrôleurs. Les structures ou les variables non alignées affectent les performances et peuvent entraîner des charges non atomiques et des mémoires. Votre kilométrage peut varier. –

8

Oui, ils peuvent l'être. Pourquoi pas? Les champs de bits dans les unions se comportent de la même manière qu'ils se comportent ailleurs. Il n'y a rien de spécial à propos des bits-fields dans les unions (ou des unions avec des bits-fields).

0

Ce n'est dangereux que si vous écrivez dans un élément d'union et lisez un élément différent. Si les détails de votre implémentation garantissent que cela ne se produit pas, alors une union contenant un bitfied (et vraisemblablement d'autres membres) a un comportement bien défini et sûr.

+0

La mise en œuvre du calage de type union n'est-elle pas définie? – detly

+1

Il ne s'agit pas de C++: le type punning through unions est parfaitement valide en C et se comporte de la même manière que 'reinterpret_cast' de C++. Corrigendum technique 3 rend cela clair. –

2

Si vous pensez au fonctionnement de l'union, vous avez la réponse, qui est oui, bien sûr (pourquoi pas)? Comme on s'y attend, l'union est assez grande pour contenir la plus grande donnée, et donc automatiquement la plus petite. Les champs de bits sont empaquetés dans des "conteneurs" et le compilateur doit être capable d'évaluer leur taille réelle finale. Ce qui suit montre quelques faits intéressants (et bien sûr est une mauvaise utilisation d'une union, mais pas pour la présence de bitfield!)

#include <stdio.h> 

union test { 
    int a:5; 
    int b:12; 
    float c; 
    double d; 
    int x; 
}; 

int main() 
{ 
    union test x; 
    printf("%d\n", sizeof(x)); 
    x.a = 31; 
    printf("%d\n", x.a); 
    printf("%d\n", x.b); 
    x.c = 1.23; 
    printf("%d\n", x.a); 
    printf("%f\n", x.c); 
    x.x = 31; 
    printf("%d\n", x.x); 
    printf("%d\n", x.a); 
    printf("%d\n", x.b); 
}