2015-10-23 3 views
1

J'essaie de générer un nombre entier en tant que binaire dans un std::ostream.Ecrit un entier rvalue dans un ostream en tant que valeur binaire

La première chose que j'ai essayé était:

int MyInt(){return 42;} 
//... 
std::ostream out; //not actually this but any ostream will do 
out<<MyInt(); 

Bien sûr convertit le int à une chaîne de caractères qui est pas ce que je veux.

J'ai aussi trouvé un moyen de le faire fonctionner:

int value=MyInt(); 
out.write(reinterpret_cast<const char*>(&value), sizeof(int)); 

Ceci produit ce que je veux mais je dois utiliser un temporaire pour maintenir la valeur en utilisant directement la fonction comme ceci:

out.write(reinterpret_cast<const char*>(&(MyInt())), sizeof(int)); 

Échec de la compilation car je ne peux pas prendre l'adresse d'un rvalue (à moins qu'il ne soit lié à une référence const).

Cela me fait essayer que:

out.write(&(const char&)(MyInt()), sizeof(int)); 

Cependant, alors qu'il ne conserve l'octet le plus petit les autres sont des ordures. Les résultats sont probablement aussi définis par la mise en œuvre pour autant que je sache, donc pas une solution recommandée, même si elle devait fonctionner. Un union peut résoudre le problème et est probablement plus agréable qu'une variable temporaire.

union IntConverter{ 
    int i; 
    char c[sizeof(int)]; 
    IntConverter(int in) :i(in){} 
}; 
out.write(IntConverter(MyInt()).c, sizeof(int)); 

Cependant, je voudrais éviter d'avoir à écrire un code plus si possible et je suis d'idées, donc je me demande s'il y a une meilleure solution pour résoudre ce problème.

+0

je suppose « sur << std :: hex << MyInt() "ne vous obtiendra pas ce que vous voulez? –

+0

'std :: hex' écrira la valeur en hexadécimal mais c'est toujours du texte. Le deuxième et dernier exemple me donne la sortie correcte (4 octets écrits, le premier octet est 42 et les autres 0). – meneldal

+1

Alors, quel est l'inconvénient d'utiliser un temporaire? Vous créez un provisoire de toute façon avec le syndicat. C'est certainement plus facile à lire que le syndicat. –

Répondre

1

Pour être en mesure de sortir facilement un int en binaire, j'utiliserais une classe wrapper avec un ami operator <<. Il pourrait facilement être modélisé pour accepter l'intégrale de différentes tailles. Par exemple:

template<typename T> 
class BinInt { 
private: 
    T i; 

public: 
    BinInt(T i): i(i) {} 
    friend std::ostream& operator << (std::ostream& os, const BinInt& b) { 
     os.write(reinterpret_cast<const char *>(&(b.i)), sizeof(T)); 
     return os; 
    } 
    T val() { 
     return i; 
    } 
}; 

Vous pouvez l'utiliser aussi simplement que:

BinInt<int> bi(0x41424344); 
BinInt<short> bs(0x4546); 
std::cout << "Val:" << bi.val() << " - repr:" << bi << std::endl; 
std::cout << "Val:" << bs.val() << " - repr:" << bs << std::endl; 

et sur un 32 bits little endian donne:

Val:1094861636 - repr:DCBA 
Val:17734 - repr:FE 
+0

Cette option est plus belle que celle de l'union. Je vais accepter si personne ne trouve quelque chose de mieux dans les prochains jours. Ce n'est pas exactement ce que je veux, mais c'est une bonne amélioration par rapport à ce que je faisais. – meneldal