2011-02-02 5 views
3

Si j'ai un struct comme ceci:Attribution d'un bit de valeur par bit

struct example 
{ 
    uint16_t bar:1; 
    uint16_t foo:1; 
}; 

, j'ai une autre variable 16 bits: uint16_t value;

Si je veux que le premier bit « valeur » pour être assigné à "example.bar", et le second bit en valeur à affecter à "example.foo", comment ferais-je cela?

EDIT:

J'ai essayé les éléments suivants:

typedef struct 
{ 
    unsigned short  in_1_16; 
    unsigned short  in_17_32; 
    unsigned short  in_33_48; 
} READSTR; 

typedef struct 
{ 
    unsigned short  chan_1_16; 
    unsigned short  chan_17_32; 
    unsigned short  chan_33_48; 
} TLM; 

void main() 
{ 
    TLM tlm; 
    tlm.chan_1_16 = 0xFFFF; 
    READSTR t675; 

    t675.in_1_16 = 0x10; 
    t675.in_17_32 = 0x9; 
    t675.in_33_48 = 0x8; 

tlm.chan_1_16 |= t675.in_1_16 & 1; 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 1); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 2); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 3); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 4); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 5); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 6); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 7); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 8); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 9); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 10); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 11); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 12); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 13); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 14); 
tlm.chan_1_16 |= t675.in_1_16 & (1 << 15); 
printf("%x", tlm.chan_1_16); 

Je suis en train de la valeur sur struct à tous ceux (0xFFFF), et je suis en train de le mettre à 0x10, peu par bit. Mais quand je cours ce code j'obtiens toujours 0xFFFF. Vous ne savez pas ce que je fais mal?

+0

Comment définissez-vous "first bit in" value ""? Le premier bit est-il le bit le plus significatif ou le bit le moins significatif? – oosterwal

+1

'uint16'? Qu'est-ce que c'est? Voulez-vous dire 'uint16_t'? –

+0

@Chris oui, je voulais dire uint16_t – Blade3

Répondre

0

essayer avec:

struct example x; 
x.bar = value & 1; 
x.foo = value & 1 << 1; 

fooN = value & 1 << N; 
+1

+1, bien que j'emballe '1 << 1' etc. dans les parens juste pour que la priorité soit claire. –

+0

Ce code est totalement nonportable car vous ne savez pas où "bar" et "foo" résident dans le champ de bits. – Lundin

+0

@Lundin: pourquoi auriez-vous besoin où ils sont, le principe du bitfield est de nommer les bits pour les adresser indépendamment, c'est au compilateur de décider où les border ... n'est-ce pas? –

1
#include <iostream> 

typedef unsigned short uint16; 

struct example 
{ 
    uint16 bar:1; 
    uint16 foo:1; 
}; 

union foo 
{ 
    struct example x; 
    uint16 value; 
}; 

int main() 
{ 
    uint16 bar = 0x01; 

    foo f; 
    f.value = bar; 

    std::cout << f.x.bar << std::endl; // display 1 
    std::cout << f.x.foo << std::endl; // display 0 
} 

EDIT
Cet extrait a été utilisé dans le code de production et utilisé pour fonctionner comme prévu. Quoi qu'il en soit, il a été testé avec des assertions statiques et des tests unitaires qui garantissaient son exactitude. Comme ils ne sont pas rapportés ici, je suis d'accord qu'il ne devrait pas être utilisé "tel quel".

Puisque vous (OP) mentionné C++, je suggère d'utiliser std::bitset classe:

#include <bitset> 

int main() 
{ 
    std::bitset<16> set(bar); 

    example x; 
    x.bar = set[0]; 
    x.foo = set[1]; 

    std::cout << x.bar << std::endl; // display 1 
    std::cout << x.foo << std::endl; // display 0 
} 
+2

Est-ce portable? http://stackoverflow.com/questions/1490092/c-c-force-bit-field-order-and-alignment –

+0

La position de bit réelle de * bar * et * foo * dépend de l'implémentation. * bar * peut être le bit le plus significatif ou le bit le moins significatif, ou dans le cas de la création de bitfields en utilisant type * int * avec un compilateur Cosmic, vous pouvez constater que les octets sont échangés. – oosterwal

+0

l'inverse ne fonctionnera pas ... c'est-à-dire, si vous faites 'fx = _example;' et 'cout << f.value' ... ne fonctionnerait pas .. – Nawaz

3

Il est impossible de dire, car les champs de bits sont très mal défini par la norme. Ce qui suit, vous ne pouvez pas savoir:

  • si le champ de bits int est traité comme int
  • signé ou non signé l'ordre des bits (lsb est où?)
  • si le champ de bits peut atteindre passé l'alignement de la mémoire de la CPU ou non
  • l'alignement des éléments de champ non-bit de la struct
  • l'alignement de la mémoire de champs de bits (vers la gauche ou vers la droite?)
  • la endianess des champs de bits
  • si les valeurs int simples qui leur sont assignées sont interprétées comme signé ou non signé
  • comment les champs de bits sont promus implicitement par les promotions entières
  • si les champs de bits signés sont un complément à ou complément à deux
  • emplacement des octets de remplissage
  • comment des bits de remplissage sont traités
  • valeurs des bits de remplissage
  • et ainsi de suite

Comme vous pouvez le constater, les champs de bits sont très très mauvais et ne devraient jamais être utilisés.La seule solution raisonnable est de réécrire le code sans champs de bits:

#define FOO 0x01U 
#define BAR 0x02U 

uint16_t value; 

value |= FOO; /* set FOO bit */ 
value &= ~FOO; /* clear FOO bit */ 

Le code ci-dessus peut être exécuté sur un compilateur C/C++ pour tout système dans le monde et vous obtiendrez le résultat escompté.

+2

Il peut être exécuté sur un compilateur C ou C++, mais pour C++ en utilisant '# define' est BAD :) –

+3

@Matthieu M. - C'est aussi mauvais que vous le pensez, et c'est aussi dangereux que vous l'ignorez. L'utilisation des macros ci-dessus est parfaitement sûre. L'utilisation d'une variable globale 'const' ne le rend pas plus ou moins sûr. Le rejet dogmatique de la caractéristique X est invariablement mal orienté. (Sauf 'gets()'. Il n'y a pas de cas d'utilisation sûr pour 'gets()'.) –

+1

@Chris: Dogmatic signifie sans raison valable, en C++ les variables 'const' sont beaucoup plus sûres que les macros car elles sont traitées par le compilateur , pas le préprocesseur, et donc respecter les règles de portée. Je noterais cependant, que j'ai utilisé un smiley après "BAD" afin de signaler que c'était surtout un jeu de mots ... –

0

Les valeurs attribuées aux champs de bits non signés sont définies comme étant modulo 2 ** N réduit, où N est le nombre de bits dans le champ de bit. Cela signifie que si vous affectez un nombre non signé à un champ de bits non signé, les N bits les moins significatifs du nombre d'origine seront utilisés.

Ainsi, étant donné struct example x, si vous voulez que le bit le moins significatif de value à placer dans x.bar vous pouvez simplement faire:

x.bar = value; 

Si vous voulez que le deuxième moins significatif peu de value à placer Dans x.foo, vous pouvez également utiliser:

x.foo = value >> 1;