Grâce au commentaire de Lincoln ci-dessous, j'ai changé cette réponse.
La réponse suivante gère correctement les entiers 8 bits au moment de la compilation. Cependant, il nécessite C ++ 17. Si vous n'avez pas C ++ 17, vous devrez faire autre chose (par exemple, fournir des surcharges de cette fonction, une pour uint8_t et une pour int8_t, ou utiliser quelque chose en plus de "if constexpr", peut-être enable_if).
template< typename T >
std::string int_to_hex( T i )
{
// Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");
std::stringstream stream;
stream << "0x" << std::setfill ('0') << std::setw(sizeof(T)*2) << std::hex;
// If T is an 8-bit integer type (e.g. uint8_t or int8_t) it will be
// treated as an ASCII code, giving the wrong result. So we use C++17's
// "if constexpr" to have the compiler decides at compile-time if it's
// converting an 8-bit int or not.
if constexpr (std::is_same_v<std::uint8_t, T>)
{
// Unsigned 8-bit unsigned int type. Cast to int (thanks Lincoln) to
// avoid ASCII code interpretation of the int. The number of hex digits
// in the returned string will still be two, which is correct for 8 bits,
// because of the 'sizeof(T)' above.
stream << static_cast<int>(i);
}
else if (std::is_same_v<std::int8_t, T>)
{
// For 8-bit signed int, same as above, except we must first cast to unsigned
// int, because values above 127d (0x7f) in the int will cause further issues.
// if we cast directly to int.
stream << static_cast<int>(static_cast<uint8_t>(i));
}
else
{
// No cast needed for ints wider than 8 bits.
stream << i;
}
return stream.str();
}
Réponse originale qui ne gère pas correctement les entiers 8 bits comme je le pensais:
La réponse de Kornel Kisielewicz est excellente. Mais un léger ajout permet de détecter les cas où vous appelez cette fonction avec des arguments de modèle qui n'ont pas de sens (par exemple, float) ou qui entraîneraient des erreurs de compilation désordonnées (par exemple, un type défini par l'utilisateur).
template< typename T >
std::string int_to_hex( T i )
{
// Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << i;
// Optional: replace above line with this to handle 8-bit integers.
// << std::hex << std::to_string(i);
return stream.str();
}
J'ai modifié ceci pour ajouter un appel à std :: to_string car les types entiers 8 bits (par exemple les std::uint8_t
valeurs passées) à std::stringstream
sont traités comme char, ce qui ne vous donne pas le résultat souhaité. Passer de tels entiers àstd::to_string
gère correctement et ne nuit pas à l'utilisation d'autres types d'entiers plus grands. Bien sûr, vous risquez de subir un léger impact sur les performances dans ces cas, car l'appel std :: to_string n'est pas nécessaire.
Remarque: j'aurais juste ajouté ceci dans un commentaire à la réponse d'origine, mais je n'ai pas le représentant à commenter.
int
type;)