8
votes

Interpréter non signé comme signé

Je travaille sur une plate-forme intégrée (bras) et je dois faire attention lorsque vous faites face à des modèles de bits. Prétendre que cette ligne est au-delà de mon influence: xxx

interprété comme non signé cela serait 206. Mais en réalité, il est signé, ressemblant ainsi à -50 . Comment puis-je continuer à utiliser cette valeur tel que signé? xxx

ni (résultant 0x10 ou 0x00 pour toutes les valeurs d'entrée) xxx

Je veux juste que les bits restent intacts, c'est-à-dire. (bar == 0xce)

Vice versa Je serais intéressé à obtenir des bit-pattes, représentant des nombres négatifs, dans des variables non signées sans gâcher le motif bit. J'utilise GCC.


4 commentaires

Conversion de signé à Unsigné conserve le motif de bits, alors signé, Char -50 deviendra 206 non signé. Passer de non signé à la signature sera le même numéro s'il peut être représenté comme signé, sinon sa mise en œuvre est définie.


Mon débogueur m'a dupé, la barre intt8_t = foo; Fonctionne juste bien sur ma plate-forme. Désolé pour ça, mais encore merci beaucoup pour les idées qui m'ont donné.


@ Sven-de: Ouais, il peut être défini par la mise en œuvre, mais la plupart des implémentations vont prendre la voie facile à sortir (plutôt que de sa saturer à son maximum de +127)


@ Sven-de: Si c'est la réponse utile à votre réponse, pourriez-vous la mettre comme une réponse et l'accepter, ou acceptez la réponse très similaire de Kerrek avec un commentaire? Il est confus d'avoir cette question marquée comme n'ayant pas encore une réponse acceptée lorsqu'il est répondu maintenant. Merci!


5 Réponses :


8
votes

Le suivant fonctionne bien pour moi, comme il se doit S> si les commentaires disent, il s'agit de la mise en œuvre définie par la mise en œuvre: xxx pré>

en C ++, vous pouvez également dire : P>

int x = static_cast<signed char>(foo);


4 commentaires

Ceci est, techniquement, UB. Il en résulte un débordement.


Intéressant - Je pensais que c'était bien défini ... Qu'en est-il de l'autre sens, jetant un caractère signé à un non signé?


Unsigné à la signature est défini par la mise en œuvre si le nombre ne peut être représenté comme signé. signé au non signé devient "le plus non signé entier congruant à la source entier (modulo 2 ^ n)". Dans la représentation du complément de deux, il suffit de conserver le même motif de bits. Voir 4.7 Conversions intégrales.


@Johnps: Je vois, merci. J'ai édité la réponse pour dire que c'est défini par la mise en œuvre.



3
votes

Quelque chose de moche le long des lignes de ceci? XXX

ne s'appuie pas sur une conversion dont le comportement n'est pas défini.


2 commentaires

Je pense que vous vouliez dire 256, pas 128, oui? Et il n'y a pas besoin de la vilaine C coulée.


@Alf: En effet, vous avez probablement raison de dire que les conversions arithmétiques habituelles signifient que la distribution (style C ou C ++) est inutile. Mais ces règles sont difficiles à retenir, je préférerais donc la laisser explicite.



0
votes

avec des chances de GCC est que les valeurs non signées sont complétés de deux deux, même sur votre plate-forme intégrée.

Le nombre 8 bits 0xce représente 0xce-256 . < / p>

Parce que le complément de deux est vraiment juste modulo 2 n , où n est le nombre de bits dans la représentation.

EDIT : HM, pour le bien de repère, je ferais mieux de donner un exemple concret: xxx

edit 2 : Je n'ai pas vu la dernière question sur la façon d'obtenir un motif de bits dans une variable non signée. C'est extrêmement facile: il suffit d'assigner. Le résultat est garanti par la norme C ++, à savoir que la valeur stockée est congruente (sur la face sur horloge égale) à la valeur attribuée, modulo 2 N .

acclamations & hth.,


1 commentaires

Voulez-vous dire "les valeurs signées sont le complément de deux"? Les valeurs non signées, bien sûr, n'ont aucun concept de signe et pas d'autre variance de la représentation des bits.



6
votes
uint8_t foo = 0xCE;          // 0b11001110
int8_t bar;
memcpy( &bar, &foo, 1 );
It even has the added bonus that 99% of compilers will completely optimise out the call to memcpy ...

0 commentaires

0
votes

Vous pouvez accéder à la représentation d'une valeur à l'aide d'un pointeur. En réinterprétant le type de pointeur, vous ne devez pas répliquer la représentation.

uint8_t foo = 0xCE;          
int8_t bar = *reinterpret_cast<int8_t*>(&foo);


6 commentaires

Cela enfreint un aliasing strict et peut donc être optimisé dès le départ du programme ou le cas échéant. Le seul moyen standard de la représentation «réinterpret» nécessite des types de manière triviale et memcpy à la destination. Espérons que le compilateur optimise que la réinterprétation de code machine que vous avez toujours souhaitée, mais que réinterpret_cast REINTERPRET_CAST à un type Type Type à lire est toujours valide.


@underscore_d Je pensais que cela a été autorisé comme "un type qui est le type signé ou non signé correspondant au type dynamique de l'objet". Peut être mon interprétation erronée de la clause.


Yup, il semble que tu as raison. Merci pour le rappel de cette ligne signée / non signée. Toutefois, réinterpret_cast n'est pas nécessaire ici et fournit probablement une probabilité plus faible (garantie) du succès qu'un simple static_cast : Stackoverflow.com/a/1751368/2757035 ... Ou suis-je juste omis à la recherche lorsque vous essayez de trouver une spécification de la manière dont réinterpret_cast convertit entre des snovessesses? Si non spécifié, je suppose que cela veut (a) tout ce qu'il veut ... ou au moins (B) Que static_cast fait, auquel cas, il n'y a pas besoin de l'aller-retour du pointeur.


@underscore_d A static_cast sur le pointeur échouera car uint8_t et int8_t est des types distincts, donc le REINIERPRET_CAST est requis ici. N3797 dit: "Un pointeur d'objet peut être explicitement converti en un pointeur d'objet d'un type différent." L'utilisation du pointeur, au lieu de la valeur, est que la question initiale indiquait que le motif de bits doit être identique dans les valeurs non signées et signées. Avec deux compléments, cela n'a pas d'importance, mais l'utilisation du pointeur est requise pour d'autres représentations.


Comme indiqué par la réponse que j'ai liée, je parlais d'un static_cast entre les valeurs , pas les pointeurs. Et avec d'autres représentations, l'Afaict La norme ne dit que le mappage effectué par REINIERPRET_CAST est défini de la mise en œuvre au mieux, ce qui ne semble pas garantir de manière fermement garantie ce que les OP veulent, juste un possible Une garantie faible qui pourrait être donnée par leur mise en œuvre ... pour l'instant.


@underscore_d Le "cartographie" fait référence à la représentation définie par la mise en œuvre du pointeur. Sinon, c'est bien défini.