Gracias al comentario de Lincoln a continuación, he cambiado esta respuesta.
La siguiente respuesta maneja correctamente las entradas de 8 bits en tiempo de compilación. Sin embargo, requiere C ++ 17. Si no tiene C ++ 17, tendrá que hacer otra cosa (por ejemplo, proporcionar sobrecargas de esta función, una para uint8_t y otra para int8_t, o usar algo además de "if constexpr", tal vez 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();
}
Respuesta original que no maneja entradas de 8 bits correctamente como pensé que lo hizo:
La respuesta de Kornel Kisielewicz es genial. Pero una pequeña adición ayuda a detectar casos en los que está llamando a esta función con argumentos de plantilla que no tienen sentido (por ejemplo, flotante) o que darían lugar a errores de compilación desordenados (por ejemplo, tipo definido por el usuario).
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();
}
He editado esto para agregar una llamada a std :: to_string porque los tipos enteros de 8 bits (por ejemplo, los std::uint8_t
valores pasados) std::stringstream
se tratan como char, lo que no le da el resultado que desea. Pasando esos enteros astd::to_string
manejarlos correctamente y no daña las cosas cuando se usan otros tipos de enteros más grandes. Por supuesto, es posible que sufra un ligero impacto en el rendimiento en estos casos, ya que la llamada std :: to_string es innecesaria.
Nota: Hubiera agregado esto en un comentario a la respuesta original, pero no tengo el representante para comentar.
int
tipo;)