Благодаря приведенному ниже комментарию Линкольна я изменил этот ответ.
Следующий ответ правильно обрабатывает 8-битные int во время компиляции. Однако для этого требуется C ++ 17. Если у вас нет C ++ 17, вам придется сделать что-то еще (например, предоставить перегрузки этой функции, одну для uint8_t и одну для int8_t, или использовать что-то помимо «if constexpr», возможно, 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();
}
Исходный ответ, который не обрабатывает 8-битные целые числа правильно, как я думал:
Ответ Корнеля Киселевича великолепен. Но небольшое дополнение помогает поймать случаи, когда вы вызываете эту функцию с аргументами шаблона, которые не имеют смысла (например, с плавающей точкой) или которые могут привести к беспорядочным ошибкам компилятора (например, определяемого пользователем типа).
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();
}
Я отредактировал это, чтобы добавить вызов std :: to_string, потому что 8-битные целые типы (например, std::uint8_t
передаваемые значения) std::stringstream
обрабатываются как char, что не дает желаемого результата. Передача таких целых чисел для std::to_string
их правильной обработки и не повредит при использовании других, более крупных целочисленных типов. Конечно, в этих случаях возможно небольшое снижение производительности, поскольку вызов std :: to_string не нужен.
Примечание: я бы просто добавил это в комментарий к исходному ответу, но у меня нет представителя для комментариев.
int
типу;)