Integer to hex string in C++
Solution 1
Use <iomanip>
's std::hex
. If you print, just send it to std::cout
, if not, then use std::stringstream
std::stringstream stream;
stream << std::hex << your_int;
std::string result( stream.str() );
You can prepend the first <<
with << "0x"
or whatever you like if you wish.
Other manips of interest are std::oct
(octal) and std::dec
(back to decimal).
One problem you may encounter is the fact that this produces the exact amount of digits needed to represent it. You may use setfill
and setw
this to circumvent the problem:
stream << std::setfill ('0') << std::setw(sizeof(your_type)*2)
<< std::hex << your_int;
So finally, I'd suggest such a function:
template< typename T >
std::string int_to_hex( T i )
{
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << i;
return stream.str();
}
Solution 2
To make it lighter and faster I suggest to use direct filling of a string.
template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I)<<1) {
static const char* digits = "0123456789ABCDEF";
std::string rc(hex_len,'0');
for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
rc[i] = digits[(w>>j) & 0x0f];
return rc;
}
Solution 3
Use std::stringstream
to convert integers into strings and its special manipulators to set the base. For example like that:
std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();
Solution 4
You can do it with C++20 std::format
:
std::string s = std::format("{:x}", 42); // s == 2a
Until std::format
is widely available you can use the {fmt} library, std::format
is based on (godbolt):
std::string s = fmt::format("{:x}", 42); // s == 2a
Disclaimer: I'm the author of {fmt} and C++20 std::format
.
Solution 5
Just print it as an hexadecimal number:
int i = /* ... */;
std::cout << std::hex << i;
Related videos on Youtube

kryptobs2000
Updated on November 20, 2021Comments
-
kryptobs2000 about 1 year
How do I convert an integer to a hex string in C++?
I can find some ways to do it, but they mostly seem targeted towards C. It doesn't seem there's a native way to do it in C++. It is a pretty simple problem though; I've got an
int
which I'd like to convert to a hex string for later printing. -
MSalters almost 12 years
sizeof(your_type)*2
is a bit ugly;numeric_limits<your_type>::digits/4
is cleaner. -
Kornel Kisielewicz almost 12 years@MSalters - quite on the contrary. Test your suggestion on the
int
type ;) -
Alan Turing almost 10 years@Kornel, great answer, but why template it? To support
long int
? -
Kornel Kisielewicz almost 10 years@LexFridman, to emit exactly the amount of hex digits as needed. Why emit 8 digits if the type is a uint8_t?
-
Alexander Oh over 8 yearsa nice answer, but beware that
to_string
is part of the namespacestd
in C++11 -
Alex over 8 years@Alex yes, it is 2014 after all... heaven forbid we'll have to start dealing with C++14 soon.
-
ov7a almost 7 yearsWARNIG: this will not work for single byte because char is always threated as char
-
ShadowRanger almost 7 yearsThis doesn't really add to the existing answers, and it's pointless to explicitly
clear
thesstream
(it will be destroyed when the function returns on the next line anyway). You could avoid the namedhexStr
entirely and justreturn sstream.str();
withoutclear
ing and get the same effect, reducing four lines of code to one. -
parasrish almost 7 yearswhen purpose of the forum is to understand the things and usage. being verbose is far better to provide clear picture, than saving lines. question was not on optimized code, and answer tries to give a modular-method way of dealing with such conversions. @ShadowRanger
-
Wolf over 6 yearsWhat is the purpose of
sstream.clear();
? Thesstream
object is automatically destroyed at the end of the scope, soreturn sstream.str();
would do it. -
parasrish over 6 years
sstream.clear
will just clear the content, before stream ends with scope end (to clear any fail and eof flags with clear). Indeed, when the scope dies, with the life-span of the stream-variable, and thereforesstream.str
can be used to return by value. [Reference : cplusplus.com/reference/ios/ios/clear/] -
ruipacheco about 6 yearsShouldn't you just return buf.str() ?
-
S.R over 5 yearsWill this work for any type? I mean also double, float, uint8_t?
-
Wolf almost 5 years@S.R It works for integral types, not for
double
andfloat
(and not for pointers) -
Wolf almost 5 years... a very pragmatic (but valid) mix of C and C++, I'm not sure about speed ... for my taste, it's a bit dense.
-
Foxcat385 almost 5 yearsI tried this and I got error error C2784: 'std::basic_ostream<_Elem,_Traits> &std::operator <<(std::basic_ostream<_Elem,_Traits> &,const std::_Smanip<_Arg> &)': could not deduce template argument for 'std::basic_ostream<_Elem,_Traits> &' from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>'
-
Foxcat385 almost 5 yearsNevermind. Another line of code in my code caused the error. If only C++ compiler knew how to tell me at which line of code the problem is happening.
-
David Gausmann almost 5 yearsYou also require #include <sstream>
-
DeveloperChris over 4 yearsThank you, brilliant answer. Bringing in a stream library 'just' to do this seems such a waste.
-
wcochran over 4 yearsIf I am formatting multiple ints, It seems that
std::setw
needs to be output to the stream for every int, whereasstd::hex
,std::setfill
,std::uppercase
, ... only need to be sent to the output stream once. This seems inconsistent? -
Lincoln about 4 yearsin my testing std::to_string(i) does not print std::uint8_t integers as hex. I think this may have to have separate conditions for both uint8_t and int8_t types, since they need to be cast to larger integers.
-
Loss Mentality about 4 years@Lincoln You are right. I don't know what I was doing at the time (months ago now) that made me thing to_string handled 8-bit ints. I even went back to the compiler version I think I was using back then, just to double check, but to_string didn't work as I said it did. So who knows? Anyway, thanks for catching this - I've edited answer to something that should work correctly.
-
Lightness Races in Orbit about 4 yearsCould show off the width deduction with e.g.
TEST_ASSERT(int_to_hex(short(0x12)) == "0012");
-
Mark Lakata almost 4 yearsI would use
std::cout<<std::hex<<i<<std::dec;
, otherwise all integers that are streamed out later will be in hex. You don't need to do that for the other answers that usestringstream
because the stream is discarded after it is used, butcout
lives forever. -
Ruslan about 3 yearsThis will still work unexpectedly for
char
(which is distinct from bothuint8_t
andint8_t
in most implementations (where they are respectivelyunsigned char
andsigned char
)). -
Loss Mentality over 2 years@ruslan Yes, also bool and wide char types all match std::is_integral and will not fail the assert. But since char is, per the std., a guaranteed unique type, as are the wide char types, you can handle all of them if desired (exceptions are un/signed char, which match the un/signed integral type of whatever width a byte is on the current machine - typically int8 - and so can't be filtered if you want to match ints of the same width as well). You can reject char, wide chars, bools by adding more terms to the the static_assert:
... && !std::is_same_v<char, T> && !std::is_same_v<bool, T>
etc... -
jaques-sam over 2 yearsThis prints
0000FFFF
for0xFFFF
. I prefer to have0xFFFF
as output. -
Code Abominator over 2 yearsI expect this will annoy everyone else in your project since so few people ever think to
<< std:dec
before pushing numbers into a stream. I thought was a widely known flaw in C++ streams? -
Jason Aller over 2 yearsThis does use some techniques not seen in the other answers. Can you please edit the answer to include some explanation of how and why it works?
-
Wade Wang over 1 yearThe header file is
#include <boost/format.hpp>
-
Haseeb Mir over 1 yearBoost doesn't come pre-installed that's why
-
Plater about 1 year@DrumM pass a 4 into the hex_len parameter then?