2010-11-04 8 views
2

Je lis quelques octets d'un flux d'octets et ils ressemblent à ceci:La différence entre signés octets et octets de parité

OUTPUT: 
48 -84 -79 -84 -73 -79 46 48 -84 

SHOULD BE: 
48 44 49 44 55 49 46 48 44 

Je voudrais les transformer en caractères ascii mais ces symboles negitive sont sème en moi une certaine confusion. Cela me fait penser que je ne comprends pas les octets signés. Qu'est-ce que je fais mal ici?

+3

Indiquez le code qui les lit. –

+0

Si possible, envoyez-nous le code où vous avez lu les octets. –

+0

Je suis en train de réduire le code maintenant. C'est un peu compliqué, et j'ai juste saisi la sortie du journal de débogage. sry, travailler dessus ... – Stephano

Répondre

9

On dirait que le bit est utilisé comme bit de parité , alors que votre code suppose qu'il est un bit de signe .

  • 48 = 011 0000: 2 bits set -> ajouter 0 -> = 48 0000 0011
  • 44 = 010 1100: 3 bits set -> ajouter 1 -> 1010 1100 = -84
  • 49 = 011 0001: 3 bits mis -> ajouter 1 -> 1011 0001 = -79
  • et ainsi de suite ...

Solution: masque loin le bit en utilisant (value & 0x7f).

+1

Whoa. Vous avez raison monsieur. Le code suppose que c'est un bit de signe, mais c'est en effet un bit de parité. Bien joué! +1 et la victoire – Stephano

+1

+1. Qui a besoin d'un débogueur quand vous avez des pouvoirs psychiques? –

2

Les lire comme des octets non signés. Explication: Le premier bit (le plus haut) est pris comme un signe +/-, pas comme un chiffre binaire normal lorsque vous l'interprétez comme un octet signé.

+1

Pas strictement correct. Les valeurs ci-dessus (non signées) 0x80 sont en effet négatives, mais ce n'est pas un "bit de signe" en complément de deux. –

+0

Et cela n'explique pas les relations entre SHOULD BE et OUTPUT. – ruslik

+1

@theatrus: La définition la plus correcte est que le bit le plus significatif a une valeur décimale de -128 au lieu de 128 dans une valeur de 8 bits signée. Cela a été familièrement appelé le "signe" pendant des décennies. Cependant, si vous définissez "bit de signe" pour signifier étroitement "un bit qui indique le signe", ce qui fonctionne par exemple en virgule flottante IEEE 754, alors le complément de deux n'a pas de "bit de signe". FWIW, invoquant cette définition de "bit de signe" implique différentes représentations pour 0 et -0. –

2

Il s'agit d'un entier signé de 8 bits. Comme les entiers 32 bits, mais avec une plage plus petite.

0

Il est possible que votre application les convertisse en int avant de les écrire. Quel est le code que vous utilisez pour générer la sortie?

1

Qu'est-ce qu'un "octet"? En langage C++ "octet" est un type char, qui est simplement un type entier ordinaire pouvant être signé ou non signé. Sur votre plateforme, le type char est probablement signé (si char est ce que vous utilisez), c'est pourquoi vous obtenez des valeurs signées. En d'autres termes, vous avez très probablement utilisé un type signé pour lire les valeurs dans, donc vous avez probablement obtenu des résultats signés.

Bien sûr, c'est juste une supposition, car sans voir le code, il n'est pas possible de dire exactement ce que vous faites.

7

Par exemple:

84 (dec): 0101 0100 
-84 (dec): 1010 1100 

44 (dec): 0010 1100 

Ce dernier (-84) est complément à deux de l'ancien (84). Avec un codage d'octets signé, si le bit le plus élevé est défini, alors il représente un nombre négatif. Par coïncidence, 44 (dec) est codé comme -84 en octets signés, sauf que son bit le plus élevé est clair.

+0

+1 Je pense que cela me le permet. Désolé, je ne peux pas montrer le code plus facilement, mais je vais m'en débarrasser moi-même. – Stephano

+0

+1 pour me mettre sur la bonne voie vers la réponse acceptée. – Sjoerd

4

Vous êtes probablement concerné par le jeu de caractères ASCII 7 bits (tout l'anglais américain s'y trouve, par exemple). Puisque vous lisez 8 bits à la fois, la meilleure chose à faire serait pour masquer le bit (ce qui est le bit de signe)

En C:

ombles lettre = dataByte & 0x7F;

-84, avec son bit haut masquée, est 44.

+0

+1 parce que vous êtes nouveau à SO et c'est une bonne réponse. – Stephano

0

Lorsque vous lisez des données à partir d'une source (un fichier, une prise réseau, etc.), il est seulement un flux de zéros et les uns. Habituellement, ils sont livrés par groupes de huit (c'est-à-dire sous la forme d'octets) mais il revient entièrement à votre code de décider comment interpréter ces bits.

Supposons un fichier contient cet octet:

10101100 

Si vous l'interprétez comme un octet signé, cela représente la valeur -84 en décimal.

Si vous l'interprétez comme un octet non signé, alors il représente la valeur 172 en décimal.

Si votre code lit des valeurs dans une variable de type char, alors vous verrez -84, car char est signé par défaut. Si vous modifiez la déclaration de la variable à unsigned char, vous verrez alors 172. Les bits sous-jacents sont les mêmes dans les deux cas, vous dites simplement à l'ordinateur de les interpréter différemment.

2

@Stephano Maintenant, nous obtenons quelque part :)

Le plus probablement votre UART est réglé sur 7 bits de données + 1 bit de parité (bit élevé est la parité), de sorte que le nombre de bits définis dans l'octet ont être pair.

Vous pouvez l'utiliser pour vérifier les erreurs, puis le réinitialiser pour obtenir le véritable caractère ASCII 7 bits.

+0

+1 également correct. Techniquement, Sjoerd est entré sous le buzzer. Bien joué cependant, acclamations mate! – Stephano

+0

Nous étions tous les deux sur la bonne voie. Je n'ai pas vu vos commentaires avant que j'aie écrit ma réponse. – Sjoerd