2010-11-04 5 views
6

J'ai deux octets, octets de 8 bits, qui devraient être lus comme: [3 bits] [4 bits] [3 bits].2 octets représentent 3 entiers dans C

Exemple:

unsigned char octet1 = 0b11111111; // binary values 
unsigned char octet2 = 0b00000011; 

Comme entiers: [7] [15] [7].

Quelqu'un peut me donner un indice par où commencer?

+6

... par où commencer * quoi *? – Flinsch

+4

Travail à domicile? Rien de mal avec les devoirs, mais les questions doivent être signalées comme telles. Cela aide la communauté à mieux situer ses réponses pour être plus utile. –

+1

Maintenant que j'en parle ... 3 + 4 + 3! = 8 ... – peoro

Répondre

3

Pas besoin de mettre les deux octets ensemble avant d'extraire les bits que nous voulons.

#include <stdio.h> 

main() 
{ 
    unsigned char octet1 = 0b11111111; 
    unsigned char octet2 = 0b00000011; 
    unsigned char n1 = octet1 & 0b111; 
    unsigned char n2 = (octet1 >> 3) & 0b1111; 
    unsigned char n3 = (octet1 >> 7) | (octet2 + octet2); 

    printf("octet1=%u octet2=%u n1=%u n2=%u n3=%u\n", 
       octet1, octet2, n1, n2, n3); 

} 
+1

Belle façon de ne pas avoir à combiner les octets comme un mot. Je pense que j'aurais écrit '(octet2 + octet2)' comme 'octet2 << 2' cependant. Aussi, cela semble ne fonctionner que si les bits les plus élevés de 'octet2' est toujours 0. Il peut être préférable de' & 0b111' la dernière expression pour se sauver des problèmes futurs. –

+0

Merci beaucoup, pour moi, il semble que l'approche la plus directe. Mais malheureusement, je n'ai pas réussi à 'résoudre' le problème soulevé par Jonas, où les bits les plus élevés ne sont pas 0. J'ai essayé: n3 = (octet1 >> 7) | (octet2 << 2); ? - Je pense que c'était supposé être << 1, au lieu de << 2? –

+1

'unsigned char n3 = (octet1 >> 7 | octet2 << 1) & 0b111;' –

1

Vous pouvez utiliser les options booléennes pour obtenir et définir les valeurs individuelles.

On ne sait pas quels bits de vos octets appliquer à chaque valeur, mais vous avez seulement besoin & (au niveau du bit), | (opérateur OR), << (décalage vers la gauche) et >> (décalage vers la droite) pour ce faire.

0

Bitfields pourrait être une option. Vous devrez peut-être remplir votre structure pour obtenir les bits à aligner comme vous le souhaitez. Reportez-vous à Bitfields in C++ ou recherchez StackOverflow pour C++ et bitfields ou vous pouvez utiliser des opérateurs bit à bit comme contour dans les autres réponses.

3
oct2| oct1 
000011|1 1111 111 
    ---- ---- --- 
    7 0xf 7 

Juste un soupçon, (en supposant qu'il est des devoirs)

1

Début de la rédaction d'un emballage/déballage fonctions pour vos hybrides 2 octets.

Si vous donc le travail avec C/C++ - vous pouvez utiliser le support intrinsèque pour cela:

struct Int3 { 
    int a : 3; 
    int b : 4; 
    int c : 3; 
}; 
2

Remarque: 0x11111111 ne veut pas dire 8 bits tous ensemble à 1. Il est un nombre hexadécimal de 4 octets, où un octet est défini sur 0x11.

0xFF est un seul octet (8 bits) lorsqu'un bit est mis à 1.

Ensuite, pour obtenir ce que vous voulez, vous pouvez utiliser pour isoler certains MACROs les bits dont vous avez besoin:

#define TOKEN1(x) ((x)>>7) 
#define TOKEN2(x) (((x)>>3) & (0xFF>>5)) 
#define TOKEN3(x) (((x)>>5) & (0xFF>>5)) 

N'a pas testé.

Une autre idée, pourrait être celle de mettre dans une union char et un struct en utilisant bitfield caractères

union { 
    struct { char a:3; char b:4; char c:3; }; 
    char x; 
}; 

De cette façon, vous pouvez utiliser x pour modifier l'octet entier, et a, b et c à accès aux jetons simples ...

Modifier: 3 + 4 + 3 = 8.

Si vous avez besoin de 10 bits, vous devez utiliser un court au lieu d'un caractère. Si, au contraire, certains de ces bits se chevauchent, la solution utilisant MACRO sera probablement plus facile: vous aurez besoin de plus d'une structure dans l'union pour obtenir le même résultat avec la deuxième solution ...

0

Voulez-vous dire? , si nous "concaténons" des octets comme octet2.octet1, nous obtiendrons 000000 [111] [1111] [111]?

Ensuite, vous pouvez utiliser les opérations de bits:

  • ">>" et "< <" pour changer les bits de votre valeur,
  • "&" pour masquer les bits
  • "+" de combiner valeurs

Par exemple, la valeur « moyenne » (qui est de longueur 4 bits) peut être reçu de la manière suivante:

middle = 15 & (octet1 >> 3); 
0
assert(CHAR_BIT == 8); 
unsigned int twooctets = (octet2 << 8) | (octet1); /* thanks, Jonas */ 
unsigned int bits0to2 = (twooctets & /* 0b0000_0000_0111 */ 0x007) >> 0; 
unsigned int bits3to6 = (twooctets & /* 0b0000_0111_1000 */ 0x078) >> 3; 
unsigned int bits7to9 = (twooctets & /* 0b0011_1000_0000 */ 0x380) >> 7; 
+2

Ne devrait pas le premier & être un |? –

+0

Oui, merci. Code corrigé. – pmg

9

Dans une sorte de pseudocode

octet1 = 0b11111111 
octet2 = 0b00000011 
word = octet1 | octet2<<8 
n1 = word & 0b111 
n2 = word>>3 & 0b1111 
n3 = word>>7 & 0b111 
+0

Vous pouvez ajouter des parenthèses pour plus de clarté. Si votre pseudo-code est comme C, alors le décalage a une plus grande priorité que '&' et '|', mais tout le monde ne le sait pas. – dan04

+0

Je ne suis pas sûr que ça puisse s'appeler pseudocode parce que c'est Ruby. Ruby a la même priorité supérieure pour '>>' à '&' et '|' que C. Je pense qu'il ne devrait pas être nécessaire de savoir que '|' est bitwise ou, '&' est bitwise et, et que Les bits '>>' et '<<' 'se déplacent à droite et à gauche pour lire le pseudocode. En tant qu'exemple de pseudo-code pour un programmeur C, il pourrait simplement fonctionner. –

+0

Merci pour votre échantillon, votre réponse a reçu le plus grand nombre de votes - mais franchement, je pense qu'il serait plus approprié de choisir celui qui est en fait un échantillon C, et ne nécessite pas la 3ème attribution de 'mot' –

4

Salut est ici une méthode qui est testé et compilé en utilisant VC++ 9

#pragma pack(1) 

union 
{ 
    struct 
    { 
     unsigned short val1:3; 
     unsigned short val2:4; 
     unsigned short val3:3; 
     unsigned short val4:6; 
    } vals; 
    struct 
    { 
     unsigned char octet1:8; 
     unsigned char octet2:8; 
    } octets; 
    short oneVal; 
} u = {0xFFFF}; 

unsigned char octet1 = 0xFF; //1 1111 111 
unsigned char octet2 = 0x03; //000000 11 
//000000 111 1111 111 0 7 15 7 
u.octets.octet1 = octet1; 
u.octets.octet2 = octet2; 
cout << "size of u.vals:" << sizeof(u.vals)<< endl; 
cout << "size of u.octets:" << sizeof(u.octets)<< endl; 
cout << "size of u.oneVal:" << sizeof(u.oneVal)<< endl; 
cout << "size of u:" << sizeof(u)<< endl; 
cout << endl; 

cout << "Your values:" << endl; 
cout << "oneVal in Hex: 0x"; 
cout.fill('0'); 
cout.width(4); 
cout<< hex << uppercase << u.oneVal << endl; 
cout << "val1: " << (int)u.vals.val1 << endl; 
cout << "val2: " << (int)u.vals.val2 << endl; 
cout << "val3: " << (int)u.vals.val3 << endl; 
cout << "val4: " << (int)u.vals.val4 << endl; 
cout << endl; 

octet1 = 0xCC; //1 1001 100 
octet2 = 0xFA; //111110 10 
//111110 101 1001 100 62 5 9 4 
u.octets.octet1 = octet1; 
u.octets.octet2 = octet2; 

cout << "Some other values:" << endl; 
cout << "oneVal in Hex: 0x"; 
cout.fill('0'); 
cout.width(4); 
cout<< hex << uppercase << u.oneVal << endl; 
cout << dec; 
cout << "val1: " << (int)u.vals.val1 << endl; 
cout << "val2: " << (int)u.vals.val2 << endl; 
cout << "val3: " << (int)u.vals.val3 << endl; 
cout << "val4: " << (int)u.vals.val4 << endl; 
cout << endl; 

octet1 = 0xCC; //1 1001 100 
octet2 = 0xFA; //111110 10 
//111110 101 1001 100 62 5 9 4 
u.oneVal = (((unsigned short)octet2) << 8) | (unsigned short)octet1; 
cout << "Some thing diffrent asignment:" << endl; 
cout << "oneVal in Hex: 0x"; 
cout.fill('0'); 
cout.width(4); 
cout<< hex << uppercase << u.oneVal << endl; 
cout << dec; 
cout << "val1: " << (int)u.vals.val1 << endl; 
cout << "val2: " << (int)u.vals.val2 << endl; 
cout << "val3: " << (int)u.vals.val3 << endl; 
cout << "val4: " << (int)u.vals.val4 << endl; 
cout << endl; 

Notez également que j'utilise #pragma pack (1) pour régler l'emballage de la structure à 1 octet .

J'ai également inclus un moyen d'affecter les deux octets dans la valeur courte unique. Est-ce que cela en utilisant le décalage bit à bit "< <" et bitwise ou "|"

Vous pouvez simplifier l'accès à u en supprimant les structures nommées. Mais je voulais montrer les tailles utilisées pour les structures.

Comme ceci:

union 
{ 
    struct 
    { 
     unsigned short val1:3; 
     unsigned short val2:4; 
     unsigned short val3:3; 
     unsigned short val4:6; 
    }; 
    struct 
    { 
     unsigned char octet1:8; 
     unsigned char octet2:8; 
    }; 
    short oneVal; 
} u = {0xFFFF}; 

L'accès serait maintenant aussi simple que

u.oneVal = 0xFACC; 

ou

u.octet1 = 0xCC; 
u.octet2 = 0xFA; 

vous pouvez également déposer soit oneVal ou octet1 et octet2 en fonction de ce que l'accès méthode que vous aimez.

+1

Vous savez votre fatigué quand 'A cela en utilisant la merde bitwise' vous fait rire. –

+0

@Jonas merci pour l'endroit. Fixé, il devrait être "A-t-il utilisé le décalage bitwise" :). –

+0

Oui, c'est la façon la plus évidente de le faire en C (pour quelqu'un qui lit le code de toute façon). – Christoffer

Questions connexes