2017-09-01 4 views
0

J'ai quelques valeurs signed 8 bit que je veux stocker sur un signed 32 bit integer.Stockez une valeur char sur un int en utilisant bitwise et gardez la valeur du signe valeur correcte lors de la récupération sans un cast

je fais que le déplacement des valeurs à l'aide décalage au niveau du bit gauche:

const auto value1 = char{90}; 
const auto value2 = char{80}; 
const auto value3 = char{70}; 
const auto value4 = char{60}; 

auto merged_value = int32_t{0}; 
merged_value |= (value1 & 0x000000FF) << 24; 
merged_value |= (value1 & 0x000000FF) << 16; 
merged_value |= (value1 & 0x000000FF) << 8; 
merged_value |= value1 & 0x000000FF; 

Maintenant, disons que je veux revenir value1 de merged_value je le ferai comme ceci:

const auto back_value1 = (merged_value >> 24) & 0x000000FF; 

Cela fonctionne grand tant que value1 est un nombre positif, mais si la valeur est négative, la valeur de retour sera erronée.

Par exemple, si value1 est -80, alors back_value1 seront 176, c'est parce que le bit le plus significatif (le bit positif ou négatif) est en position de bit 7 et non dans 31 (depuis back_value1 est un int32_t).

Maintenant, je sais que je dois juste faire un cast à char sur back_value1 et j'obtiendrai la valeur -80. Mais ce que je veux, c'est une opération sur le bit qui me donnera la valeur correcte -80 à back_value1 quand back_value1 est int32_t et sans un cast à char.

Merci

Edit:

Neil Butterworth a demandé que je posterai le code complet ici plutôt que sur un IDE en ligne, donc la voici:

#include <iostream> 
#include <bitset> 

int main() 
{ 
    const auto value = char{-80}; 
    std::cout << "value: " << (int)value << std::endl; 

    std::cout << "value bits: " << std::bitset<32>(value) << std::endl; 

    auto merged_value = uint32_t{0}; 
    merged_value |= (value & 0x000000FF) << 24; 

    const auto back_value = int32_t(merged_value >> 24) & 0xFF; 

    std::cout << "value: " << back_value << std::endl; 
    std::cout << "back_value bits: " << std::bitset<32>(back_value) << std::endl; 
} 
+1

"Je souhaite stocker sur un entier signé 32 bits." - Pourquoi cela doit-il être signé? –

+0

Il ne peut pas, peut être un 32 bits non signé aussi, car il agit simplement comme un conteneur à la fin, je viens de mettre signé pour être plus précis, mais je suppose que cela a créé une confusion. –

+5

Cela ressemble à un autre exemple où l'utilisation des types explicites corrects plutôt que 'auto' aurait résolu le problème, ou du moins l'aurait simplifié. –

Répondre

0

La réponse est que pour obtenir la valeur en tant que int32_t avec le même signe que l'original int8_t, vous devez soit:

rejetterait à un int8_t:

const auto back_value1 = int32_t(int8_t((merged_value >> 24) & 0xFF)); 

ou assurez-vous que l'octet dont vous avez besoin est à l'extrémité gauche du int32_t avant de passer à droite:

const auto back_value1 = merged_value /* << 0 */ >> 24; 
const auto back_value2 = merged_value <<8>> 24; 

Inutile de dire que je ne recommande pas le dernier.