2010-07-12 17 views
1

je un réseau de unsigned chars. Fondamentalement, j'ai un tableau de bits.C++ types de données primitives: lire non signé 30 bits

je sais que les 16 premiers bits correspond à un entier non signé et je récupérer sa valeur en utilisant (u16)(*(buffer+ 1) << 8 | *abcBuffer)

Puis vient un type de données appelé u30 qui est décrit comme suit: . La variable codage pour u30 utilise un à cinq octets, en fonction de l'amplitude de la valeur codée. Chaque octet attribue ses sept bits inférieurs à la valeur. Si le huitième octet d'un octet est défini, l'octet suivant fait également partie de la valeur.

Je ne comprends pas cette description: il est dit u30 (trente ans!) Et il dit 1 à 5 octets? J'ai aussi un autre type de données appelé s24 - three-byte signed integer value.

Comment doit-on lire (récupérer leurs valeurs) ces types de données non typiques? Toute aide serait appréciée.

Merci beaucoup!

+2

Il est 1 à 5 octets parce que vous utilisez seulement 7 bits de chaque octet, donc 4 octets ne peut représenter 28 bits; vous avez besoin de tous les 5 octets pour représenter une valeur de 30 bits. –

+0

D'où cela vient-il? Certaines anciennes architectures comme celle de PDP-10 de DEC utilisaient des octets de 6 bits. –

+0

5 * 7 = 30. Je ne vois pas la confusion ici. Pour répondre à votre question cependant: avec un 5e de tequila bon marché pour soigner votre mal de tête. –

Répondre

2

En supposant que je comprends bien (toujours une question discutable), ce qui suit lire les valeurs. Il commence à la position zéro dans cet exemple (i devrait être compensée par la position réelle dans la mémoire tampon):

unsigned int val; 
    unsigned char buf[300]; 
    int i; 
    int shift; 

    i = 0; 

    buf[0] = 0x81; 
    buf[1] = 0x3; 
    val = 0; 
    shift = 0; 
    do 
     { 
     val |= (0x7F & buf[i]) << shift; 
     shift += 7; 
     i++; 
     } while ((buf[i-1] & 0x80) && (i < 5)); 
    printf("Val = %u\n", val); 
+0

Peut-être ajouter une vérification d'erreur pour détecter le cas où le 5ème octet a trop de bits, de sorte que le résultat ne correspond pas à 30 bits? –

+0

Ambiguement dans l'OP est de savoir si la "machine" est grand ou peu endian. Si c'est un gros endian, vous devez simplement déplacer val par 7 à chaque fois dans la boucle, plutôt que de déplacer l'octet courant de n * 7 fois. On doit aussi se demander ce qui est supposé arriver si l'octet 5 a l'un de ses 6 bits les plus importants (comme le dit David). –

+0

Votre point sur l'endian-ness est correct. J'ai pensé à cela et (c'est vrai) juste pris la voie facile. J'ai simplement fait une supposition en fonction de la façon dont j'aurais écrit l'encodage (écrire les 7 bits faibles), décaler vers la droite, extraire les 7 bits suivants, etc. –

1

La description du format de codage est un peu peut-être informelle, mais devrait être suffisant. L'idée sera que vous lisez un octet (appelez-le x), vous prenez les 7 bits les plus bas x & 0x7F et en même temps vérifiez si c'est le bit le plus élevé est mis. Vous aurez besoin d'écrire une petite boucle qui fusionne les séquences de 7 bits dans une variable uint jusqu'à ce que l'octet actuel n'ait plus son bit le plus élevé.

Vous devrez déterminer si vous avez besoin de fusionner les nouveaux bits à l'extrémité supérieure ou à l'extrémité inférieure du nombre (a = (a << 7) | (x & 0x7F)). Pour cela, vous avez besoin d'une séquence de test dont vous connaissez la sortie correcte.

4
i=0;  
val = buf[i]&0x7F; 
while (buf[i++]&0x80) 
{ 
    val |= (buf[i]&0x7F)<<(i*7); 
} 
0

Pour lire la longueur variable 30 valeur binaire, vous pouvez faire quelque chose comme par exemple:

const char HIGH_BIT = 0x80; 
const char DATA_MASK = 0x7F; 
const char LAST_MASK = 0x03; // only need 2 bits of last byte 
char tmpValue = 0; // tmp holder for value of byte; 
int value = 0; holder for the actual value; 
char* ptr = buffer; // assume buffer is at the start of the 30 bit number 
for(int i = 0; i < 5; i++) 
{ 
    if(i == 4) 
    { 
     tmpValue = LAST_MASK & *ptr; 
    } 
    else 
    { 
     tmpValue = DATA_MASK & *ptr; 
    } 

    value |= tmpValue << (7 * i); 

    if(!(HIGH_BIT & *ptr)) 
    { 
     break; 
    } 
    if(i != 4) 
    { 
    ++ptr; 
    } 
} 
buff = ptr; // advance the buffer afterwards. 

@ Mark: votre réponse a été publiée alors que je tapais cela, et travaillerait à l'exception du haut octet. la valeur est seulement de 30 bits, donc seulement les 2 premiers bits de l'octet haut sont utilisés pour la valeur et vous utilisez les 8 bits entiers de la valeur.

+0

Oui en effet - je pensais juste un peu (heh heh) il y a retour pour le réparer. –